产品毕业设计网站建设,网站页面设计大小,商务网站建设的基本流程,wordpress密码可见不跳转【LeetCode 踩坑日记】No.189 轮转数组#xff1a;被 ArrayList 的初始化骗了#xff1f;
在刷算法题的过程中#xff0c;我们经常会遇到一种情况#xff1a;思路明明是正确的#xff0c;逻辑也很通顺#xff0c;但代码一跑就崩#xff0c;或者结果不对。
今天我在做 Le…【LeetCode 踩坑日记】No.189 轮转数组被 ArrayList 的初始化骗了在刷算法题的过程中我们经常会遇到一种情况思路明明是正确的逻辑也很通顺但代码一跑就崩或者结果不对。今天我在做LeetCode 189. 轮转数组时就遭遇了一个经典的 Java 集合陷阱。这篇博客将记录我从“理直气壮”到“恍然大悟”的排错过程并总结关于数组轮转的通用解法。1. 题目回顾题目给定一个整数数组nums将数组中的元素向右轮转k个位置。示例输入:nums [1,2,3,4,5,6,7], k 3输出:[5,6,7,1,2,3,4]2. 我的“完美”思路与报错代码我的第一反应非常直观创建一个新的列表list。遍历原数组计算每个元素移动k步后的新位置。如果位置超出了数组长度就绕回到开头否则直接放入新位置。使用ArrayList的set方法填值。于是我写出了以下代码// ❌ 错误示范classSolution{publicvoidrotate(int[]nums,intk){// 我以为这里创建了一个长度为 nums.length 的列表ListIntegerlist1newArrayList(nums.length);for(inti0;inums.length;i){// 这里逻辑其实有点硬编码把 k 当成了 3if(i3nums.length-1){list1.set(i3-nums.length,nums[i]);}else{list1.set(i3,nums[i]);}}System.out.println(list1);}}运行结果直接抛出java.lang.IndexOutOfBoundsException: Index 2 out of bounds for length 0。3. 深度解析为什么会报错看到报错我非常困惑我在new ArrayList(nums.length)时不是已经指定长度了吗为什么报错说length 0这里触及到了 JavaArrayList的一个核心机制Capacity容量 vs Size元素个数。Capacity容量是你告诉底层数组“请预留多少空间”。Size实际大小是列表里实际上装了多少个有效元素。当我们执行new ArrayList(10)时Java 只是在内存里开辟了一个能放10个东西的“空架子”但是架子上还没有书此时size依然是 0。add()方法是在列表尾部追加元素会使size 1。set(index, element)方法是修改现有位置的元素。它会检查index是否小于size。因为我的列表是空的Size 0任何set(index, val)操作都会被判定为越界因为那个位置上根本还没有元素可以被“修改”。修正思路如果想用“指定位置填值”的逻辑应该直接使用数组 (int[])因为数组在创建时new int[n]所有位置默认已经初始化为 0长度是固定的可以直接通过下标赋值。4. 逻辑上的二次修正除了报错我的代码逻辑还有两个问题需要解决才能通过 LeetCode 的测试A. 变量k的处理我之前的代码里写死了i 3这是针对示例 1 的特解。题目中的k是变量且k可能大于数组长度。改进使用取模运算符%。newIndex (i k) % n这行公式完美解决了越界和绕回的问题不需要写if-else判断。B. 引用修改 vs 打印题目方法的返回类型是void。这意味着仅仅System.out.println是没用的LeetCode 的判题系统会检查内存中nums数组的内容是否发生了变化。改进必须把计算出的新结果重新拷贝回原数组nums。5. 最终正确代码辅助数组法经过思考我放弃了ArrayList改用辅助数组代码变得清晰且高效// ✅ 正确解答classSolution{publicvoidrotate(int[]nums,intk){intnnums.length;// 1. 创建一个同样长度的新数组int[]newArrnewint[n];// 2. 计算新位置并赋值for(inti0;in;i){// 使用 (i k) % n 处理循环移动newArr[(ik)%n]nums[i];}// 3. 将新数组的值拷贝回原数组// System.arraycopy(newArr, 0, nums, 0, n); // 也可以用这个APIfor(inti0;in;i){nums[i]newArr[i];}}}6. 进阶思考能不能不费额外空间上面的解法使用了O(N)的额外空间创建了newArr。如果面试官问“能不能在O(1)空间复杂度下完成即不使用额外数组”这需要用到**“三次翻转法”**非常巧妙翻转整个数组。翻转前k % n个元素。翻转剩余的元素。示例[1,2,3,4,5,6,7],k3全翻转[7,6,5,4,3,2,1]翻转前3个[5,6,7, 4,3,2,1]翻转后4个[5,6,7, 1,2,3,4]-成功7. 总结这次排错让我学到了三点API 误区new ArrayList(capacity)只是申请内存不代表 List 里有元素。想按索引操作优先选数组或者先填充 List。数学之美处理循环数组索引时%取模运算比if-else判断更优雅通用。审题重要性注意函数的返回类型和副作用要求是返回新对象还是原地修改。编程就是这样一个不断犯错、理解底层、然后优化的过程。希望能帮到遇到同样报错的你