zoukankan      html  css  js  c++  java
  • LeetCode 排序

    基础部分

    912. 排序数组

    中等

    给你一个整数数组 nums,请你将该数组升序排列。

    示例 1:

    输入:nums = [5,2,3,1]
    输出:[1,2,3,5]
    

    示例 2:

    输入:nums = [5,1,1,2,0,0]
    输出:[0,0,1,1,2,5]
    

    提示:

    1. 1 <= nums.length <= 50000
    2. -50000 <= nums[i] <= 50000
    class Solution {
        public int[] sortArray(int[] nums) {
            quickSort(nums,0,nums.length-1);
            return nums;
        }
    
        private void quickSort(int[] nums, int l, int r) {
            if (l >= r) return;
            int mid = pattern(nums,l,r);
            if (mid != l){
                int tmp = nums[mid];
                nums[mid] = nums[l];
                nums[l] = tmp;
            }
            quickSort(nums,l,mid-1);
            quickSort(nums,mid+1,r);
        }
    
        private int pattern(int[] nums, int l, int r) {
            int first = nums[l];
            int i = l;
            int j = r + 1;
            while (i < j){
                do { //先判断后加,会多加一个,所以 do..while
                    i++;
                }while (nums[i] < first && i < r);
                do {
                    j--;
                }while (nums[j] > first && j > l);
                if (i >= j) break; //弄多了就换回来了,所以检查一下
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
            return j;
        }
    }
    

    215. 数组中的第K个最大元素

    中等

    在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

    示例 1:

    输入: [3,2,1,5,6,4] 和 k = 2
    输出: 5
    

    示例 2:

    输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
    输出: 4
    

    说明:

    你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

    //减治的快排
    class Solution {
        public int findKthLargest(int[] nums, int k){
            quickSort(nums,k-1,0,nums.length-1);
            return nums[k-1];
        }
    
        private void quickSort(int[] nums, int index, int l, int r) {
            if (l >= r) return;
            int mid = pattern(nums,l,r);
            if (mid != l){
                int tmp = nums[mid];
                nums[mid] = nums[l];
                nums[l] = tmp;
            }
            if (mid > index) quickSort(nums,index,l,mid-1);
            else quickSort(nums,index,mid+1,r);
        }
    
        private int pattern(int[] nums, int l, int r) {
            int first = nums[l];
            int i = l;
            int j = r + 1;
            while (i < j){
                do {
                    i++;
                }while (nums[i] > first && i < r);
                do {
                    j--;
                }while (nums[j] < first && j > l);
                if (i >= j) break;
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
            return j;
        }
    }
    
    //堆排序:建立k大小的小根堆,堆顶即为所求
    class Solution {
        public int findKthLargest(int[] nums, int k){ //O(n*logk)
            //PriorityQueue 优先级队列,底层是二叉堆
            //(n1,n2)->n1-n2 小根堆
            PriorityQueue<Integer> heap = new PriorityQueue<>((n1,n2)->n1-n2);
            for (int num : nums) {
                heap.add(num); //O(logk)
                if (heap.size() > k) heap.poll(); //O(logk)
            }
            return heap.poll();
        }
    }
    

    347. 前 K 个高频元素

    中等

    给定一个非空的整数数组,返回其中出现频率前 *k* 高的元素。

    示例 1:

    输入: nums = [1,1,1,2,2,3], k = 2
    输出: [1,2]
    

    示例 2:

    输入: nums = [1], k = 1
    输出: [1]
    

    提示:

    • 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
    • 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
    • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
    • 你可以按任意顺序返回答案。
    // 设置若干个桶,每个桶存储出现频率相同的数。桶的下标表示数出现的频率,即第 i 个桶中存储的数出现的频率为 i。
    // 把数都放到桶之后,从后向前遍历桶,最先得到的 k 个数就是出现频率最多的的 k 个数。
    class Solution {
        public int[] topKFrequent(int[] nums, int k) {
            Map<Integer,Integer> map = new HashMap<>();
            for (int num : nums)
                map.put(num,map.getOrDefault(num,0)+1); //数字频数哈希表
            List<Integer>[] buckets = new LinkedList[nums.length+1];
            for (Integer num : map.keySet()){
                int freq = map.get(num);
                if (buckets[freq] == null) //没初始化=>没有内存=>没法add
                    buckets[freq] = new LinkedList<>();
                buckets[freq].add(num); //放到对应频数的桶里
            }
            int[] res = new int[k];
            int index = 0;
            for (int i = buckets.length-1; i > 0 && index < k; i--) {
                if (buckets[i] == null) continue;
                for (Integer num : buckets[i])
                    res[index++] = num;
            }
            return res;
        }
    }
    

    451. 根据字符出现频率排序

    中等

    给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

    示例 1:

    输入:
    "tree"
    
    输出:
    "eert"
    
    解释:
    'e'出现两次,'r'和't'都只出现一次。
    因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
    

    示例 2:

    输入:
    "cccaaa"
    
    输出:
    "cccaaa"
    
    解释:
    'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
    注意"cacaca"是不正确的,因为相同的字母必须放在一起。
    

    示例 3:

    输入:
    "Aabb"
    
    输出:
    "bbAa"
    
    解释:
    此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
    注意'A'和'a'被认为是两种不同的字符。
    
    class Solution {
        public String frequencySort(String s) {
            char[] chars = s.toCharArray();
            Map<Character,Integer> map = new HashMap<>();
            for (char aChar : chars)
                map.put(aChar,map.getOrDefault(aChar,0)+1);
            List<Character>[] buckets = new LinkedList[chars.length+1];
            for (Character c : map.keySet()) {
                int freq = map.get(c);
                if (buckets[freq] == null) buckets[freq] = new LinkedList<>();
                buckets[freq].add(c);
            }
            StringBuilder res = new StringBuilder();
            for (int i = buckets.length - 1; i > 0; i--) {
                if (buckets[i] == null) continue;
                for (Character c : buckets[i]) {
                    for (int j = 0; j < i; j++) res.append(c);
                    if (res.length() == chars.length) break;
                }
            }
            return res.toString();
        }
    }
    

    75. 颜色分类

    中等

    给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

    此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

    注意:
    不能使用代码库中的排序函数来解决这道题。

    示例:

    输入: [2,0,2,1,1,0]
    输出: [0,0,1,1,2,2]
    

    进阶:

    • 一个直观的解决方案是使用计数排序的两趟扫描算法。
      首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
    • 你能想出一个仅使用常数空间的一趟扫描算法吗?
    // 0跟head换,head++;2跟tail换,tail--
    // 换就完事了,判断一样费时间
    // 注意:跟tail换时指针不往前走,因为不知道换个啥回来
    class Solution {
        public void sortColors(int[] nums) {
            int head = 0, curr = 0;
            int tail = nums.length - 1;
            int tmp;
            while (curr <= tail) {
                if (nums[curr] == 0) {
                    tmp = nums[head];
                    nums[head++] = nums[curr];
                    nums[curr++] = tmp;
                }
                else if (nums[curr] == 2) {
                    tmp = nums[curr];
                    nums[curr] = nums[tail];
                    nums[tail--] = tmp;
                }
                else curr++;
            }
        }
    }
    

    频率排序

    853. 车队

    中等

    N 辆车沿着一条车道驶向位于 target 英里之外的共同目的地。

    每辆车 i 以恒定的速度 speed[i] (英里/小时),从初始位置 position[i] (英里) 沿车道驶向目的地。

    一辆车永远不会超过前面的另一辆车,但它可以追上去,并与前车以相同的速度紧接着行驶。

    此时,我们会忽略这两辆车之间的距离,也就是说,它们被假定处于相同的位置。

    车队 是一些由行驶在相同位置、具有相同速度的车组成的非空集合。注意,一辆车也可以是一个车队。

    即便一辆车在目的地才赶上了一个车队,它们仍然会被视作是同一个车队。

    会有多少车队到达目的地?

    示例:

    输入:target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
    输出:3
    解释:
    从 10 和 8 开始的车会组成一个车队,它们在 12 处相遇。
    从 0 处开始的车无法追上其它车,所以它自己就是一个车队。
    从 5 和 3 开始的车会组成一个车队,它们在 6 处相遇。
    请注意,在到达目的地之前没有其它车会遇到这些车队,所以答案是 3。
    

    提示:

    1. 0 <= N <= 10 ^ 4
    2. 0 < target <= 10 ^ 6
    3. 0 < speed[i] <= 10 ^ 6
    4. 0 <= position[i] < target
    5. 所有车的初始位置各不相同。
    class Car{ //用类来整合比别的数据结构舒服
        int position;
        double time;
    
        public Car(int position, double time) {
            this.position = position;
            this.time = time;
        }
    }
    class Solution {
        public int carFleet(int target, int[] position, int[] speed) {
            int len = position.length;
            Car[] cars = new Car[len];
            for (int i = 0; i < len; i++)
                cars[i] = new Car(position[i],(double)(target-position[i])/speed[i]);
            Arrays.sort(cars,(x,y)->(y.position-x.position)); //按位置的降序
            int res = 0;
            for (int i = 0; i < len; i++) {
                res++;
                double head = cars[i].time;
                while (i < len && cars[i].time <= head) i++; //在我后边的,用时小于等于我的,才能追上我,和我同步到达
                i--; //for自带自增,会多加一次,所以减回来
            }
            return res;
        }
    }
    

    179. 最大数

    中等

    给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。

    示例 1:

    输入: [10,2]
    输出: 210
    

    示例 2:

    输入: [3,30,34,5,9]
    输出: 9534330
    

    说明: 输出结果可能非常大,所以你需要返回一个字符串而不是整数。

    class Solution {
        public String largestNumber(int[] nums) {
            //这样写会报错,基本数据类型都不能这么些,所以后边先把int[]转成了String[]
            //Arrays.sort(nums,(x,y) -> (String.valueOf(y)+String.valueOf(x)).compareTo(String.valueOf(x)+String.valueOf(y));
            String[] strs = new String[nums.length];
            for(int i = 0; i < nums.length; i++)
                strs[i] = String.valueOf(nums[i]);
            Arrays.sort(strs, (x, y) -> (y + x).compareTo(x + y));
            StringBuilder res = new StringBuilder();
            for(String s : strs)
                res.append(s);
            return res.toString();
        }
    }
    

    148. 排序链表

    中等

    O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

    示例 1:

    输入: 4->2->1->3
    输出: 1->2->3->4
    

    示例 2:

    输入: -1->5->3->4->0
    输出: -1->0->3->4->5
    
    class Solution {
        public ListNode sortList(ListNode head) {
            if (head == null || head.next == null) 
                return head; //递归到头只有head了,这时候开始merge
            ListNode slow = head, fast = head.next;
            while (fast != null && fast.next != null){ //二分链表
                fast = fast.next.next;
                slow = slow.next;
            }
            ListNode head2 = slow.next;
            slow.next = null;
            return merge(sortList(head),sortList(head2)); //递归合并
        }
    
        private ListNode merge(ListNode a,ListNode b) { //合并有序链表
            ListNode node = new ListNode(0);
            ListNode p = node;
            while (a != null && b != null){
                if (a.val < b.val){
                    p.next = a;
                    a = a.next;
                }else {
                    p.next = b;
                    b = b.next;
                }
                p = p.next;
            }
            p.next = a != null ? a : b;
            return node.next;
        }
    }
    

    56. 合并区间

    中等

    给出一个区间的集合,请合并所有重叠的区间。

    示例 1:

    输入: [[1,3],[2,6],[8,10],[15,18]]
    输出: [[1,6],[8,10],[15,18]]
    解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
    

    示例 2:

    输入: [[1,4],[4,5]]
    输出: [[1,5]]
    解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
    
    class Solution {
        public int[][] merge(int[][] intervals) {
            if (intervals.length < 2) return intervals;
            Arrays.sort(intervals,(a,b)->(a[0]-b[0]));
            List<int[]> list = new LinkedList<>();
            list.add(intervals[0]);
            for (int i = 1; i < intervals.length; i++) {
                int tail = list.get(list.size()-1)[1];
                if (intervals[i][0] > tail){
                    list.add(intervals[i]);
                }else if (intervals[i][1] > tail){
                    list.get(list.size()-1)[1] = intervals[i][1];
                }
            }
            int len = list.size();
            int[][] res = new int[len][2];
            for (int i = 0; i < len; i++) {
                res[i] = list.get(i);
            }
            return res;
        }
    }
    
  • 相关阅读:
    Unity3D AssetBundle相关
    [转]Unity3D新手引导开发手记
    努力多彩
    js sendBeacon
    js document.activeElement及使用
    js requestAnimationFrame
    js 1+'2' == '1'+'2'
    js scrollIntoViewIfNeeded
    汉字 3个字节
    js 浅拷贝和深拷贝
  • 原文地址:https://www.cnblogs.com/peng8098/p/leetcode02.html
Copyright © 2011-2022 走看看