6.原地修改数组
作者:互联网
原地修改数组
对于数组,尾部插入、删除比较高效,时间复杂度是O(1),但是如果在中间或者开头插入、删除元素,就会涉及数据的迁移,时间复杂度是O(N),效率较低。
有序数组/链表去重
由于数组已经排序,重复的元素一定连在一起,找到不难,但如果每找到一个重复元素就立刻删除,整个时间复杂度会达到O(N^2)
这种需求在数组相关的算法题中非常常见,通常解法就是双指针技巧中的快慢指针
让慢指针slow走在后面,快指针fast走在前面探路,找到一个不重复的元素就告诉slow并让slow前进一步。当fast指针遍历完整个数组nums后,nums[0,slow]就是不重复元素
public int removeDuplicates(int[] nums) {
if(nums.length==0){
return 0;
}
int slow = 0,fast = 0;
while(fast<nums.length){
if(nums[fast]!=nums[slow]){//不重复
slow++;//数组中的坐标
nums[slow]=nums[fast];//把不重复的数字,赋值给slow的下一位
}
fast++;//如果快慢指针数字相同,快指针向下一位
}
return slow + 1;
}
有序链表和数组去重一模一样,唯一的区别是把数组赋值操作变成操作指针
public ListNode deleteDuplicates(ListNode head) {
if(head==null) return null;
ListNode slow = head,fast = head;
while(fast!=null){
if(fast.val != slow.val){
slow.next = fast;//链表上的指针
slow = slow.next;//先赋值再移位置
}
fast = fast.next;
}
slow.next = null;
return head;
}
移动元素?
要求把 nums 中所有值为 val 的元素原地删除,依然使用双指针技巧的快慢指针。
如果fast遇到需要去除的元素,直接跳过,否则就告诉slow指针,并让slow前进一步
public int removeElement(int[] nums, int val) {
int fast =0 ,slow = 0;
while(fast< nums.length){
if(nums[fast]!=val){//不是指定值
nums[slow] = nums[fast];//先赋值再++,保证nums[0...slow-1]是不包含val元素的,最后的结果数组长度就是slow
slow++;
}
fast++;
}
return slow;
}
移动零
将所有0移到最后,相当于移除nums中的所有0,然后再把后面的元素都赋值为0
public void moveZeroes(int[] nums) {
int p = removeElement(nums,0);//去除nums中所有0,返回去除0之后的数组长度
for(;p<nums.length;p++){
nums[p] = 0;//将p之后的所有元素赋值为0
}
}
int removeElement(int[] nums, int val) {
int fast =0 ,slow = 0;
while(fast< nums.length){
if(nums[fast]!=val){//不是指定值
nums[slow] = nums[fast];//先赋值再++,保证nums[0...slow-1]是不包含val元素的,最后的结果数组长度就是slow
slow++;
}
fast++;
}
return slow;
}
}
标签:slow,nums,int,fast,原地,修改,数组,指针 来源: https://www.cnblogs.com/autumnmoonming/p/16282439.html