找出数组中重复的数和二维数组中的查找

一.找出数组中重复的数

在长度为n的数组nums里面的所有数字都在0~n-1的范围内,数组中某些数字是重复的,但不知道是哪几个,也不知道重复了几次,请找出数组中任意重复的数字

解法:
1.暴力解法:循环遍历逐个比较,我们可以利用两次循环找出一对相等的数返回

//双层循环遍历
for(int j=0;i<n-1;j++){
   for(int i=j+1;i<n;i++)
   {
    if(nums[j]==nums[i])
         return nums[j];
   }
}

这种方法的好处在于不必改变数组结构,坏处在于时间复杂度高。

2.排序相邻判断法:我们可以先对数组进行排序,然后判断第一对相邻且相等的数即可

Arrays.sort(nums);//排序
//循环判断
for(int j=0;j<n-1;j++){
   if(nums[j]==nums[j+1])
      return nums[j];
}

这种方法的坏处是改变了原有数组的结构,好处是相比暴力解法降低了时间复杂度。

3.哈希法:我们可以创建一个哈希集(HashSet)依次向哈希集中添加元素,第一个添加失败的就是重复的数

Set set=new HashSet();//新建一个hashset实例
int end=-1;
//循环数组
for(num:nums){
   if(!set.add(num))//进行添加操作顺便进行判断
   {
    end=num;
    break;
    }
   return end;
}

这种方法是比较好的,用空间换取时间,时间复杂度很低。

4.特殊解法:原地置换,根据题目我们可知,如果没有重复的数字,那么正常排序后,数字i应该在下标为i的位置上,所以思路是重头扫描数组,遇到下标为i的数字如果不是i,我们就拿它与下标为该数字
的数字交换,在交换的过程中,如果有重复的数字发生,返回之

int temp;
for(int i=0;i<nums.length;i++)//进行循环
{
//依次置位判断
 while(nums[i]!=i){
    if(nums[i]==nums[nums[i]])//出现重复
          return nums[i];
     temp=nums[i];
     nums[i]=nums[temp];
     nums[temp]=temp;
}
}

此方法很巧妙。

二.二维数组中的查找

在一个n*m的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序,请完成一个函数,输入这样一个二维数组nums[][]和整数,判断数组中是否存在该数?

解法:
1.暴力法:我们可以遍历完整个数组进行判断

int rows=nums.length;
int columns=nums[0].length;
if(nums==null||rows==0||columns==0) return false;

//双层循环遍历               
for(int i=0;i<rows;i++){
   for(int j=0;j<colums;j++){
      if(nums[i][j]==target)
          return true;
  }
}
return false;

此方法的时间复杂度为n*m,比较高

2.右上角开始的判断法:我们可以结合题中二维数组的性质,选用从右上角开始的判断排除
若右上角的数大于目标数,则左移一位
若右上角的数小于目标数,则下移一位,依次类推,直到找到目标数。

int rows=nums.length;
int columns=nums[0].length;
if(nums==null||rows==0||columns==0) return false;
int row=0;
int column=columns-1;
while(row<rows&&column>=0){

   int num=nums[row][column];
   
   if(num==target)  return true;
   
   else if(num>target)  column--;//如果num>target,指针左移
   
   else row++;//如果num<target指针下移
}
return false;

此方法的时间复杂度仅为n+m,相比暴力解题更加优秀。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员小牧之

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

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

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

打赏作者

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

抵扣说明:

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

余额充值