leetcode题解-75. Sort Colors && 442. Find All Duplicates in an Array

75, 题目:

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.

click to show follow up.

Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.

Could you come up with an one-pass algorithm using only constant space?

这道题比较简单,其实就是一个排序。但题目中说了不能使用sort函数,所以我们首先按照提示中的two-pass方法,这种方法效率很高,是解决本题的最好思路,也很简单,就是第一次循环统计0和1出现的次数,然后第二次循环给数组重新复制。代码入下:

    public void sortColors(int[] nums) {
        int a=0, b=0;
        for(int num : nums){
            if(num == 0)
                a++;
            else if(num == 1)
                b++;
        }
        for(int i=0; i<nums.length; i++){
            if(i<a)
                nums[i] = 0;
            else if(i < a+b)
                nums[i] = 1;
            else
                nums[i] = 2;
        }
    }

另外一种思路是in-place方法,这种方法只需要遍历数组一次,但是因为包含很多赋值操作,所以代码效率较低,这里提供两种方法实现,第一种是分别使用三个变量来记录0的个数,0和1的个数,012的总个数,然后每遍历一个数字,如果是0则进行三次赋值操作,如果是1则进行两次,如果是2则进行一次。执意要先给2赋值,再给1赋值,最后给0赋值。
第二种方法是进行交换。代码入下;

    public void sortColors1(int[] nums) {
        int n = nums.length, n0 = -1, n1 = -1, n2 = -1;
        for (int i = 0; i < n; ++i) {
            if (nums[i] == 0)
            {
                nums[++n2] = 2; nums[++n1] = 1; nums[++n0] = 0;
            }
            else if (nums[i] == 1)
            {
                nums[++n2] = 2; nums[++n1] = 1;
            }
            else if (nums[i] == 2)
            {
                nums[++n2] = 2;
            }
        }
    }

    public void sortColors2(int[] nums) {
        int n=nums.length, j = 0, k = n - 1;
        for (int i = 0; i <= k; ++i){
            if (nums[i] == 0 && i != j)
                swap(nums, i--, j++);
            else if (nums[i] == 2 && i != k)
                swap(nums, i--, k--);
        }
    }

    public void swap(int[] nums, int a, int b){
        int tmp = nums[a];
        nums[a] = nums[b];
        nums[b] = tmp;
    }

442, 题目:

Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements that appear twice in this array.

Could you do it without extra space and in O(n) runtime?

Example:
Input:
[4,3,2,7,8,2,3,1]

Output:
[2,3]

本题也很简单,是求出数组中的重复数字。第一种简单的思路是将数组进行排序,然后判断两个相邻数字是否相等。第二种方法是使用map来保存数组中已经出现过的数字,如果已经出现过则添加到列表中。第三种方法是遍历数组,将出现的数字对应下标出的数字便为负值,然后判断每个数字对应下表出的数字是否为负数,如果是则说明该数字已经出现过添加到结果列表中。需要注意的是每次求下标时我们都要对该数字进行绝对值操作,因为该数可能已经被变成其负数。三种方法的代码如下:

    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> res = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0; i<nums.length-1; i++){
            if(nums[i] == nums[i+1]) {
                res.add(nums[i]);
                i++;
            }
        }
        return res;
    }

    public List<Integer> findDuplicates1(int[] nums) {
        List<Integer> res = new ArrayList<>();
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums){
            if(map.containsKey(num))
                res.add(num);
            else
                map.put(num, 1);
        }
        return res;
    }

    public List<Integer> findDuplicates2(int[] nums) {
        List<Integer> res = new ArrayList<>();
        int index;
        for(int i=0; i<nums.length; i++){
            index = Math.abs(nums[i]) - 1;
            if(nums[index] < 0)
                res.add(Math.abs(index+1));
            nums[index] = -nums[index];
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值