LeetCode 分类练习(2)—— 三向切分 partition 思想的应用

75. Sort Colors

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note:
You are not suppose to use the library's sort function for this problem.

假定数组中只有 0,1,2,对此数组进行排序。

思路:

1、使用一个数组统计输入数组中 0、1 、 2 的出现次数
2、对输入数组重新赋值

1、使用三向切分的思想,将数组中的元素按照 <1、 ==1 、>1 的顺序排列

package com.leetcode.sort;

public class SortColors {
    // 使用 计数排序
//    public void sortColors(int[] nums) {
//        int[] count = {0, 0, 0};
//        for (int num : nums)
//            count[num]++;
//        int index = 0;
//        int k = 0;
//        for (int n : count) {
//            while (n != 0) {
//                nums[index++] = k;
//                n--;
//            }
//            k++;
//        }
//    }
    // 使用 快速排序的三向切分思想
    public void sortColors(int[] nums) {
        // 假设在 nums[] 的最前端加上一个 nums[-1] = 1
        int lt = -1, i = 0, gt = nums.length;    // [0...lt] == 0  [gt...n-1] == 2
        while (i < gt) {
            if (nums[i] == 0)
                swap(nums, i++, ++lt);
            else if (nums[i] == 1)
                i++;
            else // nums[i] == 2
                swap(nums, i, --gt);
        }
    }

    public void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
//        int[] nums = {1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0};
        int[] nums = {2, 1};
        SortColors sortColors = new SortColors();
        sortColors.sortColors(nums);
        for (int num : nums)
            System.out.print(num + " ");
    }


}

88. Merge Sorted Array

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.

给定两个有序数组 nums1 和 nums2,把 nums2 归并到 nums1 变为一个有序的数组

思路:
1、从 nums1 和 nums2 的尾部(有元素的位置开始),开始向前遍历,选择两者中较大的元素依次放入 nums1 的尾部(最初是空的)
2、直到两者中的任意一者中的元素用尽时
3、若此时 nums2 中还有元素,则将 nums2 中的剩余数据按序全部放入 nums1 中

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        while(m > 0 && n > 0){
            if(nums1[m-1] > nums2[n-1]){
                nums1[m+n-1] = nums1[m-1];
                m--;
            }else{
                nums1[m+n-1] = nums2[n-1];
                n--;
            }
        }
        while(n>0){
            nums1[m+n-1] = nums2[n-1];
            n--;
        }
    }
}
package com.leetcode.sort;

import java.util.Arrays;

// 88 Merge Sorted Array

public class MergeSortedArray {
    // 简单的归并排序思路
    public void merge(int[] nums1, int m, int[] nums2, int n) {

//        int[] aux = Arrays.copyOfRange(nums1, 0, m);
//        int i = 0, j = 0;
//        for (int k = 0; k < m + n; k++) {
//            if (i >= m) {
//                nums1[k] = nums2[j];
//                j++;
//            }else if (j >= n){
//                nums1[k] = aux[i];
//                i++;
//            }else if (aux[i] > nums2[j]) {
//                nums1[k] = nums2[j];
//                j++;
//            } else if(aux[i] <= nums2[j]){
//                nums1[k] = aux[i];
//                i++;
//            }
//        }

        int i = m - 1;  // 指向 nums1[] 中数据的末尾
        int j = n - 1;  // 指向 nums2[] 中数据的末尾
        int k = m + n - 1;  // 指向 nums1[] 中需要写入数据的最后一个下标
        while (i >= 0 && j >= 0) {
            if (nums1[i] > nums2[j])
                nums1[k--] = nums1[i--];
            else
                nums1[k--] = nums2[j--];
        }
        while (j >= 0)
            nums1[k--] = nums2[j--];
    }

    // 从后向前 向 nums1[] 数组[m...m+n-1]区间内填充数据,不需要额外空间
    // 即使 nums2[] 中的数据先被用尽,nums2[] 中原有的数据也是相对有序的
//    public void merge(int nums1[], int m, int nums2[], int n) {
//        int i = m - 1;  // 指向 nums1[] 中数据的末尾
//        int j = n - 1;  // 指向 nums2[] 中数据的末尾
//        int k = m + n - 1;  // 指向 nums1[] 中需要写入数据的最后一个下标
//        while (i >= 0 && j >= 0)    // 当 nums1 和 nums2 中还有数据时,向 num1[k] 中存入较大的数据
//            nums1[k--] = (nums1[i] > nums2[j]) ? nums1[i--] : nums2[j--];
//        while (j >= 0)  // 当原来 nums1[] 中的数据用尽后,将 nums2 中剩下的数据存入 nums1 中
//            nums1[k--] = nums2[j--];
//    }

    public static void main(String[] args) {
        int[] nums1 = {6, 7, 0, 0, 0};
        int m = 2;
        int[] nums2 = {2};
        int n = 1;
//        int[] nums1 = {1};
//        int m = 1;
//        int[] nums2 = {};
//        int n = 0;
        MergeSortedArray mergeSortedArray = new MergeSortedArray();
        mergeSortedArray.merge(nums1, m, nums2, n);
        for (int num : nums1)
            System.out.print(num + " ");
    }
}

215. Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

找到数组中第 k 大的元素

思路:

1、应用快速排序的 partition 的思想

1、使用优先队列

package com.leetcode.sort;

// 215 FindKthLargest

public class FindKthLargest {
    public int findKthLargest(int[] nums, int k) {
        int n = nums.length;
        return solve(nums, 0, n - 1, k-1);
    }

    private int solve(int[] nums, int l, int r, int target) {
        int p = partition(nums, l, r);
        if (p == target)
            return nums[p];
        else if (p > target)
            return solve(nums, l, p-1, target);
        else
            return solve(nums, p+1, r, target);
    }

    private int partition(int[] nums, int l, int r) {
        int temp = nums[l];
        int i = l + 1, j = l;
        for (; i <= r; i++) {
            if (nums[i] > temp)
                swap(nums, i, ++j);
        }
        swap(nums, l, j);
        return j;
    }

    private void swap(int[] nums, int a, int b) {
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    }

    public int[] generateRandomArray(int n, int rangeL, int rangeR) {
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = ((int)(Math.random() * (rangeR - rangeL + 1) + rangeL));
        return arr;
    }

    public static void main(String[] args){
        FindKthLargest findKthLargest = new FindKthLargest();
        int[] nums = findKthLargest.generateRandomArray(10, 0, 30);
        for (int num: nums)
            System.out.print(num + " ");
        System.out.println();

        int target = 3;
        System.out.print(findKthLargest.findKthLargest(nums, target));
        System.out.println();

//        QuickSort.sort(nums);
//        for (int num: nums)
//            System.out.print(num + " ");
//        System.out.println();

    }

}
    public int findKthLargest(int[] nums, int k) {
        Queue<Integer> queue = new PriorityQueue<>(new MyComparator());
        for(int num:nums)
            queue.add(num);
        while (queue.size() > nums.length - k +1)
            queue.remove();
        return queue.peek();
    }

    class MyComparator implements Comparator{
        @Override
        public int compare(Object o1, Object o2) {
            int num1 = (int) o1;
            int num2 = (int) o2;
            if (num1 < num2)
                return 1;
            else if (num1 > num2)
                return -1;
            return 0;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值