刷题日记02

本题是排序类题目,难度为简单,复盘一下做题过程。

题目:给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

提示:

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -109 <= nums1[i], nums2[j] <= 109

说实话理解这题的要求之后,我就有思路了,现将nums2和nums1合并,然后再排序,排序的方式刚好我刚学完,决定用快速排序。因此这题关键就在于如何将两个数组合并,合并的关键点就在于我要找到nums1正确的位置将nums2的值赋值过去。

看了示例后,这题我最开始的合并思路是这样想的:

三个示例代表了三种情况。第一个就是正常情况,因为nums1是升序排列,所以我要找到第一个为0的元素的索引,然后从这个索引开始把nums2的值对应存进去;第二个是nums2是空数组,长度为0,所以不用合并,对nums1排序即可;第三个是nums1自己的长度为0,nums2长度为1,这种情况直接将nums2[0]赋值给nums1[0]即可;

进行了以上分析,我就开始写合并程序了,一代合并程序如下:

//先把两个数组合并成一个
//定义一个指针,指向nums1第一个为0的元素
int index = 0;
//先要判断是否能合并,如果n==0,就没有合并的必要,对nums1进行排序就好
//如果n!=0,就把nums1的第一个为0的索引找到就行
if (n != 0){
   while (nums1[index] != 0){
   index++;
}
for (int i = 0; i < nums2.length; i++) {
    nums1[index] = nums2[i];
    index++;
}

写完之后我感觉我这可对了,老厉害了,在写完排序代码之后就兴奋的点了提交,果不其然,解答失败。当时我惊了,他的给输入nums1竟然是这样的[-1,0,0,3,3,3,0,0,0],还有负数的操作,然后我就知道是我想简单了,不能通过在第一个为0的元素位置就开始赋值。

偷摸看了眼题解,恍然大悟,是真的简单呀,于是就有了二代合并代码

for (int i = 0;i < n;i++){
            nums1[i+m] = nums2[i];
        }

能看出来真的简单,只要想明白了nums1的长度问题就行了。nums1总长度为m+n,m就是真实数值的长度,并且这m个数已经升序排列了,后面n个数都是0。那也就是说第m个元素开始不都是0吗,都应该被nums2赋值。这下合并过程就清晰了,后面的排序代码不就随便写了吗。

附上我的完整小趴菜代码

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        //   //先把两个数组合并成一个
        // //定义一个指针,指向nums1第一个为0的元素
        // int index = 0;
        // //先要判断是否能合并,如果n==0,就没有合并的必要,对nums1进行排序就好
        // if (n != 0){
        //     while (nums1[index] != 0){
        //         index++;
        //     }
        //     for (int i = 0; i < nums2.length; i++) {
        //         nums1[index] = nums2[i];
        //         index++;
        //     }
        // }
        for (int i = 0;i < n;i++){
            nums1[i+m] = nums2[i];
        }
        //合并之后进行排序[1,2,3,4,5,6]
        sort(nums1);  
    }
    //排序
    public static void sort(int[] a){
        int lo = 0;
        int hi = a.length - 1;
        sort(a,lo,hi);
    }
    public static void sort(int[] a,int lo,int hi){
        if (lo >= hi){
            return;
        }

        //获取分界值索引
        int partition = partition(a, lo, hi);

        sort(a,lo,partition - 1);
        sort(a,partition + 1,hi);
    }

    public static int partition(int[] a,int lo,int hi){
        //确定基准值
        int key = a[lo];
        int right = hi + 1;
        int left = lo;

        while (true){
            //从右边开始找
            while (less(key,a[--right])){
                if(right == lo){
                    break;
                }
            }

            //从左边开始找
            while (less(a[++left],key)){
                if (left == hi){
                    break;
                }
            }

            //判断结束条件
            if (left >= right){
                break;
            }else {
                exch(a,left,right);
            }

        }
        //交换基准值和right所在处的值
        exch(a,lo,right);
        return right;
    }
    //比较大小
    public static boolean less(Integer v,Integer w){
        return v.compareTo(w) < 0;
    }

    //交换
    public static void exch(int[] a,int i,int j){
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
}

这代码结果还挺厉害,我都没想到还能打败这老些人哈哈哈

#你们的毕业论文什么进度了##你觉得一个人能同时学好硬件和软件吗##硬件人如何看待稚晖君从华为离职##你的秋招进展怎么样了##我的求职思考#
全部评论
这道题应该用双指针才是最快的
1 回复
分享
发布于 2023-01-09 12:26 广东

相关推荐

34 2 评论
分享
牛客网
牛客企业服务