程序员面试金典10.*

10.1合并排序的数组

在这里插入图片描述
这个就从后往前加入到新数组里就行。如果B的下标是-1则结束,A的下标是-1则一直加B的元素。

class Solution {
public:
    void merge(vector<int>& A, int m, vector<int>& B, int n) {
        int p1 = m - 1, p2 = n - 1;
        int tail = m + n - 1;
        int cur;
        while(p1>=0 ||p2>=0)
        {
            if(p1==-1)
            A[tail--]=B[p2--];
            else if(p2==-1)
            return;
            else
            {
                if(A[p1]<B[p2])
                A[tail--]=B[p2--];
                else
                A[tail--]=A[p1--];
            }
        }
    }
};

10.02变位词组

在这里插入图片描述用一个大哈希表模拟就行,用Java写的过程中注意各种函数名

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> res=new ArrayList<List<String>>();
        Map<String,List<String>> map=new HashMap<>();
        for(int i=0;i<strs.length;i++){
            char[] arr=strs[i].toCharArray();
            Arrays.sort(arr);
            String s=new String(arr);
            if(!map.containsKey(s)){
                List<String> temp=new ArrayList<>();
                temp.add(strs[i]);
                map.put(s,temp);
            }else{
                map.get(s).add(strs[i]);
            }
        }
        for(String key:map.keySet()){
            res.add(map.get(key));
        }

        return res;

    }
}

1.在右边的所有New,都是new HashMap<>(),这种,有<>也有()的
2.String[] strs是没有size()的,只有length;
3.字符串转换为字符数组,便于后序排序,char[] arr=strs[i].toCharArray();
4.对字符数组排序,并且会改变字符数组。Arrays.sort(arr);
5.在一个HashMap中查找包不包含这个键。map.containsKey(s)
6.在一个HashMap中添加一个元素,map.put(key,value), map.put(s,temp);
7.在一个HashMap中得到一个Key背后的元素。map.get(key);

10.03搜索旋转数组

在这里插入图片描述
旋转数组一定是,递增序列,中断,递增序列。
搜索的话,二分,先找到中断值,也就是最小值。
然后假设把左边的移动到右边,具体做法,在arr里面,下标都要对n取余。

class Solution {
public:
    int search(vector<int>& arr, int target) {
        int n=arr.size();
        while(n>1&&arr[n-1]==arr[0]) n--;  //让最左边和最右边不相同
        //求最小值的索引
        int l=0,r=n-1;
        while(l<r){
            int mid=(l+r)>>1;
            if(arr[mid]<=arr[r]) r=mid;
            else l=mid+1;
        }
        //求target的索引
        r=l+n-1;
        if(target<arr[l]) return -1;
        while(l<r){
            int mid=(l+r)>>1;
            if(arr[mid%n]>=target) r=mid;
            else l=mid+1;
        }
        if(arr[l%n]==target) return l%n;
        return -1;

    }
};

10.05稀疏数组搜索

在这里插入图片描述
有序则二分

class Solution {
public:
    int findString(vector<string>& words, string s) {
        int l=0,r=words.size()-1;
        while(l<=r)
        {
            int mid=l+r>>1;
            // 遇到空字符串时,mid右移,直到遇到非空字符串为止
            while(mid>l&&words[mid].empty())mid++;
            if(words[mid]==s)return mid;
            else if(words[mid]>s)r=mid-1;
            else l=mid+1;
        }
        return -1;

    }
};

10.09排序矩阵查找

在这里插入图片描述
从右上角开始寻找。通过比较决定向下走还是向左走。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0) {
            return false;
        }
        int m = matrix.length, n = matrix[0].length, row = 0, col = n - 1;
        while (row < m && col >= 0) {
            if (matrix[row][col] < target) {
                row++;
            } else if(matrix[row][col] > target) {
                col--;
            } else {
                return true;
            }
        }

        return false;
    }
}

10.10 数字流的秩

在这里插入图片描述
树状数组可以高效的计算前缀和,其查询前缀和点更新(修改)都可以在O(logN)时间内完成
计算c[i]对应的区间长度,要用到Lowbit,即求一个数的最后一个非0的位置
lowbit(10100)=00100
int lowbit(int i) { return i & (-i); }
查询前缀和,去把所有的前缀c[i]的值都加上。而c[i]的直接前驱为c[i-lowbit(i)]
int sum(int i){
int s=0;
for(;i>0;i-=lowbit(i)) s+=c[i];
return s;}
点更新,要对所有后缀c[i]进行修改,而c[i]的直接后缀为c[i+lowbit(i)]
void add(int i,int z){
for(;i<n;i+=lowbit(i)) c[i]+=z; }
注意:树状数组下标从1开始,因为lowbit(0)=0会出现死循环
查询区间和,求a[i]+…+a[j],则用sum(j)-sum(i-1)
int sum(int i,int j){ return sum(j)-sum(i-1); }
代码如下:

class StreamRank {
    public int lowbit(int i) {   return i & (-i);  }
    public int sum(int j){
        int s=0;
        for(int i=j;i>0;i-=lowbit(i))  s+=c[i];
        return s;
    }
    public void add(int j,int z){
        for(int i=j;i<n;i+=lowbit(i)) c[i]+=z; 
    }
    public int sum(int i,int j){ return sum(j)-sum(i-1); }
    private int[] c;
    private int n=50002;

    public StreamRank() {
        c=new int [n+1];

    }
    
    public void track(int x) {
        add(x+1,1);

    }
    
    public int getRankOfNumber(int x) {
        return sum(x+1);

    }
}

前面四个函数是固定的,sum有一个参数的(前缀和),也有俩参数的(区间和)
为什么要用x+1,因为x的值可能为0,这样会死循环,所以统一加一。.

10.11 峰与谷

这个题没意思,可以直接排序。贪心也很简单。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值