算法题—数据结构(数组)

208 阅读6分钟

1.二维数组的查找

因为左下角的值,右边都比这个大,上边都比这个值小,所以每次把它和target值比较,等于target值就返回true,小于target值就往这一行的右边找,大于target值就往这一列上边找。这样的好处就是每一次比较都可以排除一行或一列,降低时间复杂度。

public class Solution {
    public boolean Find(int target, int [][] array) {
        int r=array.length;
        if(r==0)return false;
        int c=array[0].length;
        if(c==0)return false;
        c=0;
        r=r-1;
        while(c<array[0].length&&r>=0){
            if(target==array[c][r]){
                return true;
            }else if(target>array[c][r]){
                c++;
            }else if(target<array[c][r]){
                r--;
            }
        }
        return false;
    }
}

2.旋转数组的最小数字

二分法

链接:https://www.nowcoder.com/questionTerminal/9f3231a991af4f55b95579b44b7a01ba?answerType=1&f=discussion
来源:牛客网

int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.empty())
            return 0;
 
        int low = 0;
        int high = rotateArray.size() - 1;
        int mid = 0;
 
        while(low < high){
            // 子数组是非递减的数组,10111
            if (rotateArray[low] < rotateArray[high])
                return rotateArray[low];
            mid = low + (high - low) / 2;
            if(rotateArray[mid] > rotateArray[low])
                low = mid + 1;
            else if(rotateArray[mid] < rotateArray[high])
                high = mid;
            else low++;
        }
        return rotateArray[low];
    }

3.调整数组顺序使奇数位于偶数前面

技巧

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

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

sollution1:选举

链接:https://www.nowcoder.com/questionTerminal/e8a1b01a2df14cb2b228b30ee6a92163?answerType=1&f=discussion
来源:牛客网

class Solution {
public:
    int MoreThanHalfNum(vector<int> numbers) {
        int n = 0;
        int ret;
 
        for(size_t i=0;i<numbers.size();i++){
            if(n == 0){
                ret = numbers[i];
                n = 1;
            }else{
                if(ret == numbers[i]){
                    n ++;
                }else{
                    n--;
                }
            }
        }
        return ret;
    }
};

sollution2:排序找中间数,判断该数个数有没有过半

链接:https://www.nowcoder.com/questionTerminal/e8a1b01a2df14cb2b228b30ee6a92163?answerType=1&f=discussion
来源:牛客网

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array == null || array.length == 0)return 0;
        int preValue = array[0];//用来记录上一次的记录
        int count = 1;//preValue出现的次数(相减之后)
        for(int i = 1; i < array.length; i++){
            if(array[i] == preValue)
                count++;
            else{
                count--;
                if(count == 0){
                    preValue = array[i];
                    count = 1;
                }
            }
        }
        int num = 0;//需要判断是否真的是大于1半数,这一步骤是非常有必要的,因为我们的上一次遍历只是保证如果存在超过一半的数就是preValue,但不代表preValue一定会超过一半
        for(int i=0; i < array.length; i++)
            if(array[i] == preValue)
                num++;
        return (num > array.length/2)?preValue:0;
 
    }
}

5.把数组排成最小的数

链接:www.nowcoder.com/questionTer… 来源:牛客网

在这里自定义一个比较大小的函数,比较两个字符串s1, s2大小的时候,先将它们拼接起来,比较s1+s2,和s2+s1那个大,如果s1+s2大,那说明s2应该放前面,所以按这个规则,s2就应该排在s1前面。

链接:https://www.nowcoder.com/questionTerminal/8fecd3f8ba334add803bf2a06af1b993?answerType=1&f=discussion
来源:牛客网

import java.util.ArrayList;
public class Solution {
 
    public String PrintMinNumber(int [] numbers) {
        if(numbers == null || numbers.length == 0)return "";
        for(int i=0; i < numbers.length; i++){
            for(int j = i+1; j < numbers.length; j++){
                int sum1 = Integer.valueOf(numbers[i]+""+numbers[j]);
                int sum2 = Integer.valueOf(numbers[j]+""+numbers[i]);
                if(sum1 > sum2){
                    int temp = numbers[j];
                    numbers[j] = numbers[i];
                    numbers[i] = temp;
                }
            }
        }
        String str = new String("");
        for(int i=0; i < numbers.length; i++)
            str = str + numbers[i];
        return str;
 
    }
}

6.数字在排序数组中出现的次数

二分

链接:https://www.nowcoder.com/questionTerminal/70610bf967994b22bb1c26f9ae901fa2?f=discussion
来源:牛客网

//因为data中都是整数,所以可以稍微变一下,不是搜索k的两个位置,而是搜索k-0.5和k+0.5
//这两个数应该插入的位置,然后相减即可。
class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        return biSearch(data, k+0.5) - biSearch(data, k-0.5) ;
    }
private:
    int biSearch(const vector<int> & data, double num){
        int s = 0, e = data.size()-1;     
        while(s <= e){
            int mid = (e - s)/2 + s;
            if(data[mid] < num)
                s = mid + 1;
            else if(data[mid] > num)
                e = mid - 1;
        }
        return s;
    }
};

7.数组中只出现一次的数字

//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.HashMap;
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        //hashmap的用法
        HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
        //HashMap<Integer,Integer> hm=new HashMap<Integer, Integer>();
        for(int i=0;i<array.length;i++){
            if(hm.containsKey(array[i])){
                hm.put(array[i],2);
            }else{
                hm.put(array[i],1);
            }
        }
        int count=0;
        for(int i=0;i<array.length;i++){
            if(hm.get(array[i])==1){
                if(count==0){
                    num1[0]=array[i];
                    count++;
                }else{
                    num2[0]=array[i];
                }
            }
        }
    }
}

8.数组中重复的数字

public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    这里要特别注意~返回任意重复的一个,赋值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        //哈希太麻烦了
        //直接用数组标记
        boolean[]k=new boolean[length];
        for(int i=0;i<length;i++){
            if(k[numbers[i]]==true){
                duplication[0]=numbers[i];
                return true;
            }
            k[numbers[i]]=true;
        }
        return false;
    }
}

9.构建乘积数组

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        //数的东西暂时看着头晕
        //对分成两部分 每个数都是先从第一个部分0--i-1乘 第二个部分从n-1--i+1乘
        //先记住这个规律:被隔开的数组要计算可以分两部分
        int len=A.length;
        int[]B=new int[len]; 
        int res=1;
        for(int i=0;i<len;i++){
            B[i]=res;
            res*=A[i];
        }
        res=1;
        for(int i=len-1;i>=0;i--){
            B[i]*=res;
            res*=A[i];
        }
        return B;
    }
}

10.最短无序连续子数组

#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
            //先排序,后比较
            vector<int> vn;
            int len=nums.size();
            if(len==1)return 0;
            int ans=0;
           for(int i=0;i<len;i++){
                vn.push_back(nums[i]);
            }
            sort(nums.begin(),nums.end());
            int r=len-1;int l=0;
            bool flag=0;
            for(int i=0;i<len;i++){
                if(nums[i]!=vn[i]){
                    l=i;
                    flag=1;
                    break;
                }
            }
            for(int i=len-1;i>=0;i--){
                if(nums[i]!=vn[i]){
                    r=i;
                    break;
                }
            }
            if(flag==1)
            ans=r-l+1;
            else
            ans=0;
            return ans;

    }
}

11.移动零

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int l=nums.size();
        int lastnonzero=0;
        for(int i=0;i<l;i++){
            if(nums[i]!=0){
                nums[lastnonzero++]=nums[i];
            }
        }
        for(int i=lastnonzero;i<l;i++){
            nums[i]=0;
        }
        
    }
};

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

1.hashmap

2.用下标做标记 思路:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {

           for(int i=0;i<nums.size();i++){
               int index=(int)fabs(nums[i]*1.0)-1;
               if(nums[index]>0)
               nums[index]=-nums[index];
           } 
           vector<int> ans;
           for(int i=0;i<nums.size();i++){
               if(nums[i]>0){
                   ans.push_back(i+1);
               }
           }
           return ans;
    }
};

13.两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int ,int >mp;
        vector<int >res;
        for(int i=0;i<nums.size();i++){
            int compliment=target-nums[i];
            if(mp.count(compliment)>0){
                res.push_back(mp[compliment]);
                res.push_back(i);
                break;
            }
            mp[nums[i]]=i;
        }
        return res;
    }
};

14.删除排序数组的重复项

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size()==0)return 0;
        int i=0;
        for(int j=1;j<nums.size();j++){
            if(nums[i]!=nums[j]){
                i++;
                nums[i]=nums[j];
            }
        }
        return i+1;
    }
};