zoukankan      html  css  js  c++  java
  • 牛客网剑指offer数组题目总结(共13道)

    牛客网剑指offer数组题目总结(共13道)

    1、二维数组中的查找(剑指1)

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

    class Solution {
    public:
        bool Find(int target, vector<vector<int> > array) {
            if(array.empty()) return false;
            int i=0,j=array[0].size()-1;
            while(i<array.size()&&j>=0){
                if(array[i][j]==target) return true;
                else if(array[i][j]<target) i++;
                else  j--;
            }
            return false;
        }
    };
    

    2、调整数组顺序使奇数位于偶数前面(剑指13)

    输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

    法一:额外申请一个vector先保存奇数再保存偶数。

    class Solution {
    public:
        void reOrderArray(vector<int> &array) {
           vector<int> temp;
           int i=0;
           for(i=0;i<array.size();i++){
               if(array[i]%2==1) temp.push_back(array[i]);
           }
           for(i=0;i<array.size();i++){
               if(array[i]%2==0) temp.push_back(array[i]);
           }
           for(i=0;i<temp.size();i++)
               array[i]=temp[i];
          
        }
    };
    

    法二:借助插入排序的思想可以保证稳定性。

    class Solution {
    public:
        void reOrderArray(vector<int> &array) {
           int i=0,k=0,j=0;
           for(i=0;i<array.size();i++){
               if(array[i]%2==1){
                   int j=i;
                   while(j>k){
                       int temp=array[j];
                       array[j]=array[j-1];
                       array[j-1]=temp;
                       j--;
                   }
                   k++;
               }
           }
          
        }
    };
    

    3、顺时针打印矩阵(剑指19)

    输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

    class Solution {
    public:
        vector<int> printMatrix(vector<vector<int> > matrix) {
            vector<int> ans;
            if(matrix.empty()) return ans;
            int row1=0,row2=matrix.size()-1,col1=0,col2=matrix[0].size()-1;
            int cnt=matrix.size()*matrix[0].size();
            int x=0,y=0;
            for(x=0,y=0;cnt>0;cnt--){
                ans.push_back(matrix[x][y]);
                if(x==row1){
                    if(y<col2) y++;
                    else if(y==col2) x++;
                    continue;
                }
                if(y==col2){
                    if(x<row2) x++;
                    else  if(x==row2) y--;
                    continue;
                }
                if(x==row2){
                    if(y>col1) y--;
                    else if(y==col1) x--;
                    continue;
                }
                if(y==col1){
                    if(x>row1+1) x--;
                    else if(x==row1+1)
                    {
                        y++;
                        row1++;
                        row2--;
                        col1++;
                        col2--;
                    } 
                    continue;
                }
            }
            return ans;
        }
    };
    

    4、数组中出现次数超过一半的数字 (剑指28,简单题)

    数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

    class Solution {
    public:
        int MoreThanHalfNum_Solution(vector<int> numbers) {
            int size=numbers.size();
            map<int,int> m;
            for(int i=0;i<numbers.size();i++){
                m[numbers[i]]++;
                if(m[numbers[i]]>size/2) return numbers[i];
            }
            return 0;
        }
    };
    

    5、最小的k个数 (剑指29)

    multiset指定排序方式greater实现最大堆。

    class Solution {
    public:
        vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
            vector<int> ans;
            if(k<=0||k>input.size()) return ans;
            multiset<int,greater<int>> m;
            multiset<int,greater<int>>::iterator it;
            for(int i=0;i<input.size();i++){
                if(m.size()<k){
                    m.insert(input[i]);
                }
                else{
                    it=m.begin();
                    if(input[i]<*it){
                        m.erase(it);
                        m.insert(input[i]);
                    }
                }
            }
            for(it=m.begin();it!=m.end();it++)
                ans.push_back(*it);
            return ans;
        }
    };
    

    6、把数组排成最小的数 (剑指32)

    输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323

    class Solution {
    public:
        static bool cmp(int a,int b){
            string a1=to_string(a);
            string b1=to_string(b);
            return a1+b1<b1+a1;
        }
        string PrintMinNumber(vector<int> numbers) {
            string ans="";
            sort(numbers.begin(),numbers.end(),cmp);
            for(int i=0;i<numbers.size();i++){
                string s=to_string(numbers[i]);
                ans+=s;
            }
            return ans;
        }
    };
    

    7、数组在排序数组中出现的次数(剑指37)

    巧妙使用二分

    class Solution {
    public:
        int GetNumberOfK(vector<int> data ,int k) {
            return find(data,k+0.5)-find(data,k-0.5);
        }
        int find(vector<int> data,double k){
            int l=0,r=data.size()-1;
            while(l<=r){
                int mid=(l+r)/2;
                if(data[mid]<k) l=mid+1;
                else r=mid-1;
            }
            return r;
        }
    };
    

    8、数组中只出现一次的数字(剑指40)

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

    解题思路:所有数抑或,得到的是只出现一次的数字的抑或,找到这个数字中为1的一个位置,说明在此位置两个数的位不同,将所有数按照该位为1或0分为两类,在两类中数字相抑或,可以得到这两个数字。

    class Solution {
    public:
        void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
            int len=data.size();
            if(len<2) return;
            int temp=0;
            for(int i=0;i<data.size();i++)
                temp^=data[i];
            int index=0;
            while((temp&1)==0&&index<32){
                temp=temp>>1;
                index++;
            }
            for(int i=0;i<data.size();i++){
                if(judge(data[i],index))
                    *num1^=data[i];
                else *num2^=data[i];
            }
        }
        bool judge(int i,int index){
            i=i>>index;
            return i&1;
        }
    };
    

    9、和为S的两个数字(剑指42)

    输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

    对应每个测试案例,输出两个数,小的先输出。

    两边找:

    class Solution {
    public:
        vector<int> FindNumbersWithSum(vector<int> array,int sum) {
            vector<int> ans;
            if(array.empty()) return ans;
            int i=0,j=array.size()-1;
            while(i<j){
                if(array[i]+array[j]==sum){
                    ans.push_back(array[i]);
                    ans.push_back(array[j]);
                    break;
                }
                else if(array[i]+array[j]>sum) j--;
                else i++;
            }
            return ans;
        }
    };
    

    10、数组中重复的数字(剑指50,同leetcode287)

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

    例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

    class Solution {
    public:
        // Parameters:
        //        numbers:     an array of integers
        //        length:      the length of array numbers
        //        duplication: (Output) the duplicated number in the array number
        // Return value:       true if the input is valid, and there are some duplications in the array number
        //                     otherwise false
        bool duplicate(int numbers[], int length, int* duplication) {
            for(int i=0;i<length;i++){
                int index=numbers[i]%length;
                if(numbers[index]>=length){
                    *duplication=index;
                    return true;
                }
                numbers[index]+=length;
            }
            return false;
        }
    };
    

    11、构建乘积数组(剑指51 leetcode238与此相同)

    给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * ... * A[n-1],B[n-1] = A[0] * A[1] * ... * A[n-2];)

    class Solution {
    public:
        vector<int> multiply(const vector<int>& A) {
            int len=A.size(),i;
            vector<int> B(len,1);
            if(len<=1) return B;
            B[0]=1;
            for(i=1;i<len;i++)
                B[i]*=B[i-1]*A[i-1];
            int temp=1;
            for(i=len-2;i>=0;i--){
                temp*=A[i+1];
                B[i]*=temp;
            }
            return B;
        }
    };
    

    12、滑动窗口的最大值(剑指64,同leetcode239)

    给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

    解法:借助双端队列

    class Solution {
    public:
        vector<int> maxInWindows(const vector<int>& num, unsigned int size)
        {
            vector<int> ans;
            deque<int> q;
            for(int i=0;i<num.size();i++){
                while(!q.empty()&&num[q.back()]<num[i]) q.pop_back();
                while(!q.empty()&&i-q.front()+1>size) q.pop_front();
                q.push_back(i);
                if(size!=0&&i>=size-1) ans.push_back(num[q.front()]);
            }
            return ans;
        }
    };
    

    13、机器人的运动范围(剑指66)

    地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7=18。但是,它不能进入方格(35,38),因为3+5+3+8=19。请问该机器人能够达到多少个格子?

    class Solution {
    public:
        int movingCount(int threshold, int rows, int cols)
        {
            if(threshold<=0||rows<=0||cols<=0) return 0;
            vector <vector<bool>> visited(rows,vector<bool> (cols,false));
            int ans=Count(threshold,rows,cols,0,0,visited);
            return ans;
        }
        int Count(int threshold, int rows, int cols,int x,int y,vector <vector<bool>> &visited){
            int count=0;
            if(x>=0&&x<rows&&y>=0&&y<cols&&!visited[x][y]&&judge(threshold,x,y)){
                visited[x][y]=true;
                count=1+Count(threshold,rows,cols,x+1,y,visited)
                    +Count(threshold,rows,cols,x,y+1,visited)
                    +Count(threshold,rows,cols,x-1,y,visited)
                    +Count(threshold,rows,cols,x,y-1,visited);
            }
            return count;
        }
        bool judge(int threshold, int x, int y){
            int temp=0;
            while(x!=0){
                temp+=x%10;
                x/=10;
            }
            while(y!=0){
                temp+=y%10;
                y/=10;
            }
            return temp<=threshold;
        }
    };
    
  • 相关阅读:
    Web功能测试常用方法
    linux常用指令集说明
    Linux常用指令集
    Web测试
    APP常用测试方法总结
    软件测试笔试题初级篇
    Java 接口自动化系列--用例类之BaseCase 基础父类
    Java + Selenium 系列之失败操作截图及调用
    Java + Selenium 系列之Allure报告集成
    Java 接口自动化系列--工具类之数据库连接与操作
  • 原文地址:https://www.cnblogs.com/yjcoding/p/13216907.html
Copyright © 2011-2022 走看看