【剑指offer】第一层

二维数组中查找

题目描述
在这里插入图片描述

思路

  • 遍历法

只要是这种查找的题都有一个通解就是遍历,显然如果是面试那么offer就要?了,代码自行写,本质就是一个二维数组

  • 利用条件法(瞎取的)

从题可以看出每一行都是左右递增每一列都是上下递增,那么我们就可以利用这个特性,

target和第一行的最后一个元素比,那么会出现俩种状况

  1. targe大于最后元素
    因为是左右递增,那么targe就不会在当前行,直接排除当前行
  2. targe小于最后元素
    因为是上下递增那targe就不在当前列,直接排除当前列

代码:

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) 
    {
        //1.查找本质就是排除
        //2.数组从左到右、从上到下都是递增的
        //3.利用这一特性就可以一次排除一行或者一列
        
        int  row =0;//行
        int  lin=array[0].size()-1;//列
        while(row<array.size()&&lin>=0)
        {
            if(array[row][lin]<target)//小于说明不在这一行
            {
                row++;
            }
            else if(array[row][lin]>target)//大于说明不在这一列
            {
                lin--;
            }
             else
             {
                    return true;//上面的情况都不是说明找到了
             }
        }
        return false;//循环下来没有找到说明没有
    }
};

题目链接

旋转数组中最小的数字

题目描述
在这里插入图片描述

思路

  • 遍历
  • sort排序(利用库)
  • 双指针遍历(利用条件)

题说是非降序的数组,且是旋转过来的如 1,2,3,4 --> 3,4,1,2可以看出如果相邻的俩个数前一个比后一个大那么那个值就是最小数,但是这个本质也是遍历,就是少走几次循环罢了

代码:

 class Solution {
public://双指针法
    int minNumberInRotateArray(vector<int> rotateArray)
    {
        int prev=0;
        int next=1;
        if(rotateArray[prev]<rotateArray[next]&&rotateArray[next]==rotateArray[rotateArray.size()-1])//处理特殊情况,只有俩个数据,或者只有一个数据的情况
        {
            return rotateArray[prev];
        }
         while(next<rotateArray.size())
         {
             if(rotateArray[prev]>rotateArray[next])
             {
                 break;
             }
             prev=next++;
         }
        return rotateArray[next];
        
    }
};
  • 二分查找法(利用条件)

同样利用非递减,旋转这俩个条件,数列:4,5,1,2,3
思路如图所示:
在这里插入图片描述

代码:

class Solution
{
public://二分法
     int minNumberInRotateArray(vector<int> rotateArray)
       {
         int left=0;
         int right=rotateArray.size()-1;
         
         while(left<right)//条件
         {
           if(rotateArray[left]<rotateArray[right])//特殊情况[1,2,2,2,2],这个也叫非递减。。。。,也可以把判断写在二分失效这,建议写着效率高
           {
               return rotateArray[left];
           }
              if(left+1==right)//当左右left与right相邻时right一定是最小值
                  {
                      break;
                  }
             int middle=(left+right)/2;
              if(rotateArray[left]==rotateArray[right]&&rotateArray[right]==rotateArray[middle])//该数列中多个重复数字,二分法失效
               {
                  int mini=rotateArray[left++];
                  while(left<=right)
                  {
                      if(rotateArray[left]<mini)
                      {
                          mini=rotateArray[left];
                      }
                      left++;
                  }
                  return mini;
               }
             if(rotateArray[left]<=rotateArray[middle])//reft~middle属于一个区间
             {
                 left=middle;
             }
             else
             {
                 //middle~right属于一个区间
                 right=middle;
             }
         }
         return rotateArray[right];
       } 
};

上述思路中推荐使用二分法,你如果觉得不好把控,你可以写双指针法,那么面试官会觉得你利用了原有条件,会给你加分,实在没有看出来你也可以使用sort,顺便问问面试官可不可以调用系统的接口,不行的话你在秀一下自己写快排的能力面试官看你写的不错也会给你加分,但是写出二分法offer到手

题目链接

数组中出现次数超过一半的数字

题目:
在这里插入图片描述

思路

  • 排序取中值

题目说,一定会有解,那么一个值出现一半那么拍完序,那么中间部分的值一定就是你要找的值
在这里插入图片描述

  • 塔防法

看着名字是不是很不一样哈哈哈,其实也可以叫保卫萝卜法

1. 选取第一个数字为弓箭手,且他有一个血条初始值1

2 .遇到相同数则加血,不同则扣血,当血被扣完时,谁杀死“弓箭手”,谁就是新的弓箭手,如此往复

3. 预防数组中没有值出现次数超过一半长度的值

代码:


//塔防法
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers)
    {
        int guard=numbers[0];
        int hp=1;
       for(int i =1;i<numbers.size();i++)//寻找幸存的弓箭手
       {
            if(numbers[i]==guard)
            {
                hp++;
            }
            else
            {
                hp--;
            }
           if(hp==0)//更换哨兵
            {
               guard=numbers[i];
               hp=1;
            }
       }
        int count=0;
     for(int i =0;i<=numbers.size();i++)//判断是否存在,可以不写题目标注一定有解
     {
         if(numbers[i]==guard)
         {
             count++;
         }
     }
       return count>numbers.size()/2?guard:0;
    }
};

题目链接


絮絮叨叨的家常

这篇博客之后你需要认识一个概念就是查找的本质就是排除,效率高就是一次排除的多(二分),效率低(遍历)

在这里插入图片描述
在这里插入图片描述

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
 

)">
< <上一篇
下一篇>>