刷题日记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
-10
9
<= nums1[i], nums2[j] <= 10
9
说实话理解这题的要求之后,我就有思路了,现将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; } }
这代码结果还挺厉害,我都没想到还能打败这老些人哈哈哈
#你们的毕业论文什么进度了##你觉得一个人能同时学好硬件和软件吗##硬件人如何看待稚晖君从华为离职##你的秋招进展怎么样了##我的求职思考#