Java算法练习6
- 1.15 [506. 相对名次](https://leetcode.cn/problems/relative-ranks/)
- 1.16 [215. 数组中的第K个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/)
- 1.17 [23. 合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/)
- 1.18 [LCR 059. 数据流中的第 K 大元素](https://leetcode.cn/problems/jBjn9C/)
- 1.19 [1337. 矩阵中战斗力最弱的 K 行](https://leetcode.cn/problems/the-k-weakest-rows-in-a-matrix/)
- 1.20 [1464. 数组中两元素的最大乘积](https://leetcode.cn/problems/maximum-product-of-two-elements-in-an-array/)
- 1.21 [1054. 距离相等的条形码](https://leetcode.cn/problems/distant-barcodes/)
1.15 506. 相对名次
给你一个长度为
n
的整数数组score
,其中score[i]
是第i
位运动员在比赛中的得分。所有得分都 互不相同 。运动员将根据得分 决定名次 ,其中名次第
1
的运动员得分最高,名次第2
的运动员得分第2
高,依此类推。运动员的名次决定了他们的获奖情况:
- 名次第
1
的运动员获金牌"Gold Medal"
。- 名次第
2
的运动员获银牌"Silver Medal"
。- 名次第
3
的运动员获铜牌"Bronze Medal"
。- 从名次第
4
到第n
的运动员,只能获得他们的名次编号(即,名次第x
的运动员获得编号"x"
)。使用长度为
n
的数组answer
返回获奖,其中answer[i]
是第i
位运动员的获奖情况。示例 1:
输入:score = [5,4,3,2,1] 输出:["Gold Medal","Silver Medal","Bronze Medal","4","5"] 解释:名次为 [1st, 2nd, 3rd, 4th, 5th] 。
示例 2:
输入:score = [10,3,8,9,4] 输出:["Gold Medal","5","Bronze Medal","Silver Medal","4"] 解释:名次为 [1st, 5th, 3rd, 2nd, 4th] 。
class Solution {public String[] findRelativeRanks(int[] score) {int n = score.length;String[] s = new String[n];int[] a = new int[n];for(int i=0;i < n;i++ ){a[i]=score[i];}Arrays.sort(a);for(int i=0;i < n;i++ ){for(int j=0;j < n;j++ ){if(score[i] == a[j]){if(n-j==1){s[i] = "Gold Medal";}else if(n-j==2){s[i] = "Silver Medal";}else if(n-j==3){s[i] = "Bronze Medal";}else{s[i] = n - j +"";}}}}return s;}
}
1.16 215. 数组中的第K个最大元素
给定整数数组
nums
和整数k
,请返回数组中第**k**
个最大的元素。请注意,你需要找的是数组排序后的第
k
个最大的元素,而不是第k
个不同的元素。你必须设计并实现时间复杂度为
O(n)
的算法解决此问题。示例 1:
输入: [3,2,1,5,6,4], k = 2 输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4 输出: 4
class Solution {public int findKthLargest(int[] nums, int k) {int n = nums.length;return quickSort(nums,0,n-1,n - k + 1);}public int quickSort(int[] nums,int left,int right,int k){int base = nums[left],start = left,end = right;while(left < right){while(left < right && nums[right] >= base){right--;}nums[left] = nums[right];while(left < right && nums[left] <= base){left++;}nums[right] = nums[left];}nums[left] = base;int num = left - start + 1;if(num < k){return quickSort(nums,left + 1,end,k - num);}if(num > k){return quickSort(nums,start,left -1,k);}return nums[left];}
}
1.17 23. 合并 K 个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [ 1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
示例 2:
输入:lists = [] 输出:[]
示例 3:
输入:lists = [[]] 输出:[]
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeKLists(ListNode[] lists) {PriorityQueue<ListNode> queue = new PriorityQueue(new Comparator<ListNode>() {public int compare(ListNode o1,ListNode o2){return o1.val - o2.val;}});for(int i = 0;i < lists.length;i++){while(lists[i] != null){queue.add(lists[i]);lists[i] = lists[i].next;}}ListNode flag = new ListNode();ListNode head = flag;while(!queue.isEmpty()){flag.next = queue.poll();flag = flag.next;}flag.next = null;return head.next;}
}
1.18 LCR 059. 数据流中的第 K 大元素
设计一个找到数据流中第
k
大元素的类(class)。注意是排序后的第k
大元素,不是第k
个不同的元素。请实现
KthLargest
类:
KthLargest(int k, int[] nums)
使用整数k
和整数流nums
初始化对象。int add(int val)
将val
插入数据流nums
后,返回当前数据流中第k
大的元素。示例:
输入: ["KthLargest", "add", "add", "add", "add", "add"] [[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]] 输出: [null, 4, 5, 5, 8, 8]解释: KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]); kthLargest.add(3); // return 4 kthLargest.add(5); // return 5 kthLargest.add(10); // return 5 kthLargest.add(9); // return 8 kthLargest.add(4); // return 8
class KthLargest {PriorityQueue<Integer> queue;int k;public KthLargest(int k, int[] nums) {this.k = k;queue = new PriorityQueue();for(int i = 0;i < nums.length;i++){queue.add(nums[i]);}}public int add(int val) {queue.add(val);while(queue.size() > k){ //确保优先队列中保持剩余k个最大的值queue.poll();}return queue.peek();}
}/*** Your KthLargest object will be instantiated and called as such:* KthLargest obj = new KthLargest(k, nums);* int param_1 = obj.add(val);*/
1.19 1337. 矩阵中战斗力最弱的 K 行
给你一个大小为
m * n
的矩阵mat
,矩阵由若干军人和平民组成,分别用 1 和 0 表示。请你返回矩阵中战斗力最弱的
k
行的索引,按从最弱到最强排序。如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。
军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。
示例 1:
输入:mat = [[1,1,0,0,0], [1,1,1,1,0], [1,0,0,0,0], [1,1,0,0,0], [1,1,1,1,1]], k = 3 输出:[2,0,3] 解释: 每行中的军人数目: 行 0 -> 2 行 1 -> 4 行 2 -> 1 行 3 -> 2 行 4 -> 5 从最弱到最强对这些行排序后得到 [2,0,3,1,4]
示例 2:
输入:mat = [[1,0,0,0], [1,1,1,1], [1,0,0,0], [1,0,0,0]], k = 2 输出:[0,2] 解释: 每行中的军人数目: 行 0 -> 1 行 1 -> 4 行 2 -> 1 行 3 -> 1 从最弱到最强对这些行排序后得到 [0,2,3,1]
class Solution {public int[] kWeakestRows(int[][] mat, int k) {int[] ind = new int[mat.length]; //用来记录每行1的个数int[] result = new int[k];for(int i = 0;i < mat.length;i++){ int sum = 0;for(int j = 0;j < mat[i].length;j++){ //计算该行的1的个数if(mat[i][j] == 0) break; //如果遇到0则直接跳出sum++;}ind[i] = sum; //记录该行个数到数组}for(int j = 0;j < k;j++){ //遍历前k个小的int min = 101; //用来记录最小值int minInd = -1; //用来记录最小值下标for(int i = 0 ;i < mat.length;i++){ //查找数组ind中最小值if(min > ind[i]) {min = ind[i];minInd = i;}if(i == mat.length-1) { result[j] = minInd; //将最小值的下标记录到result数组ind[minInd] = 101; //将最小值修改防止重新遍历到}}}return result;}
}
1.20 1464. 数组中两元素的最大乘积
给你一个整数数组
nums
,请你选择数组的两个不同下标i
和j
*,*使(nums[i]-1)*(nums[j]-1)
取得最大值。请你计算并返回该式的最大值。
示例 1:
输入:nums = [3,4,5,2] 输出:12 解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12 。
示例 2:
输入:nums = [1,5,4,5] 输出:16 解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。
示例 3:
输入:nums = [3,7] 输出:12
class Solution {public int maxProduct(int[] nums) {PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){public int compare(Integer o1, Integer o2) {return o2 - o1;}});for(int i = 0; i < nums.length;i++){queue.add(nums[i]);}return (queue.poll() - 1 )* (queue.poll() -1);}
}
1.21 1054. 距离相等的条形码
在一个仓库里,有一排条形码,其中第
i
个条形码为barcodes[i]
。请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:barcodes = [1,1,1,2,2,2] 输出:[2,1,2,1,2,1]
示例 2:
输入:barcodes = [1,1,1,1,2,2,3,3] 输出:[1,3,1,3,2,1,2,1]
class Solution {public int[] rearrangeBarcodes(int[] barcodes) {int n = barcodes.length;Map<Integer,Integer> count = new HashMap();//用来记录数组barcodes中个元素的个数for(int barcode:barcodes){if(!count.containsKey(barcode)){count.put(barcode,1);}else{count.put(barcode,count.get(barcode)+1);}}//Map不能直接排序,需要将Map转换为list然后进行排序List<Map.Entry<Integer, Integer>> list = new ArrayList<Map.Entry<Integer, Integer>>(count.entrySet()); //转换为listCollections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {return o2.getValue().compareTo(o1.getValue());}}); //按照Map中的value进行降序排序int[] b = new int[n]; //用来记录重新排好序的数组int ind = 0;//将重新排列好的数组存入bfor (int i = 0; i < list.size(); i++) { for(int j = 0;j < list.get(i).getValue();j++){b[ind] = list.get(i).getKey();ind++;}} int[] res = new int[n];int idx = 0; // 获取排序数组的元素的索引for(int i = 0; i < n; i += 2){res[i] = b[idx++]; // 先填充新数组的偶数索引}for(int i = 1; i < n; i += 2){res[i] = b[idx++]; // 再填充新数组的奇数索引}return res;}
}