原地置换,手动模拟哈希表

剑指 Offer 03. 数组中重复的数字

法1:HASHSET 

class Solution {
    public int findRepeatNumber(int[] nums) {
         Set<Integer> set=new HashSet<>();
        for(int num:nums){
            if(!set.add(num)){
                  return num;
            }
        }
        return -1;
    }
}

 法2:原地置换(下标与当前值是否相同-- 下标1 当前值1)

如果没有重复数字,那么正常排序后,数字i应该在下标为i的位置,所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话,(假设为m),那么我们就拿与下标m的数字交换。在交换过程中,如果有重复的数字发生,那么终止返回

class Solution {
    public int findRepeatNumber(int[] nums) {
        int temp;
        for(int i=0;i<nums.length;i++){
            while (nums[i]!=i){
                if(nums[i]==nums[nums[i]]){
                    return nums[i];
                }
//交换是必须的,不等就必然要交换。
//注意交换时候下标是t,。。。因为后面变了。
                temp=nums[i];
                nums[i]=nums[temp];
                nums[temp]=temp;
            }
        }
        return -1;
    }
}
 

41. 缺失的第一个正数

class Solution {
    public int firstMissingPositive(int[] nums) {
        int len=nums.length;
        for (int i = 0; i <len ; i++) {
                  /*
       只有在 nums[i] 是 [1, len] 之间的数,并且不在自己应该呆的位置, nums[i] != i + 1 ,
        并且 它应该呆的位置没有被同伴占有(即存在重复值占有)	nums[nums[i] - 1] != nums[i] 的时候才进行交换

        为什么使用 while ? 因为交换后,原本 i 位置的 nums[i] 已经交换到了别的地方,
        交换后到这里的新值不一定是适合这个位置的,因此需要重新进行判断交换
        如果使用 if,那么进行一次交换后,i 就会 +1 进入下一个循环,那么交换过来的新值就没有去找到它该有的位置
         比如 nums = [3, 4, -1, 1] 当 3 进行交换后, nums 变成 [-1,4,3,1],
         此时 i == 0,如果使用 if ,那么会进入下一个循环, 这个 -1 就没有进行处理
        */
            while(nums[i]>0 && nums[i]<=len && nums[i]!=nums[nums[i]-1]){
                int t=nums[i];
                nums[i]=nums[t-1];
                nums[t-1]=t;
            }
        }
        for (int j = 0; j <len ; j++) {
            if(nums[j]!=j+1) return j+1;
        }
        return len+1;
    }
}

442. 数组中重复的数据 

因为给定题目  值为 1---n  而下标是从0开始  所以 对应 值减一 

当前数值-1  作为下标  的 值 变为负数

int[] arr=new int[]{3,2,4,11,33};

比如3 修改对应下标为2的位置的数也就是4 变为 -4;

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> ans=new ArrayList<>();
        int len=nums.length;
          for(int i=0;i<len;i++){
             int num= Math.abs(nums[i])-1;
             if(nums[num]<0) ans.add(num+1);
             nums[num]= - nums[num];
          }
         return ans; 
    }
}

448. 找到所有数组中消失的数字

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
            List<Integer> ans=new ArrayList<>();
            int len=nums.length;
            //值   1 2 3 4
            //下标 0 1 2 3
            for(int i=0;i<len;i++){
                int index=Math.abs(nums[i])-1;
               if(nums[index]>0)  nums[index]= -nums[index];
            }
            for(int i=0;i<len;i++){
               if(nums[i]>0) ans.add(i+1);
            }
      return ans;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello World程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值