Java算法练习6

这篇文章介绍了如何使用Java解决LeetCode平台上的一些算法问题,包括计算相对排名、找出数组中第K大元素、合并升序链表、数据流中第K大元素、矩阵战斗力最弱的K行、数组两元素的最大乘积以及重新排列条形码,以满足特定条件。
摘要由CSDN通过智能技术生成

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,请你选择数组的两个不同下标 ij*,*使 (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()); //转换为list
        Collections.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;
       //将重新排列好的数组存入b
        for (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;
    }
}
  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值