文章目录
- 10.1合并排序的数组
- 10.02变位词组
- 10.03搜索旋转数组
- 10.05稀疏数组搜索
- 10.09排序矩阵查找
- 10.10 数字流的秩
- 10.11 峰与谷
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写的过程中注意各种函数名
用一个大哈希表模拟就行,用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 峰与谷
这个题没意思,可以直接排序。贪心也很简单。



















