Leetcode: Algorithm

1. Boyer-Moore Voting Algorithm

identify the majority element (frequency > n/2)

 

class Solution {
    public int majorityElement(int[] nums) {
        int count = 0;
        Integer candidate = null;

        for (int num : nums) {
            if (count == 0) {
                candidate = num;
            }
            count += (num == candidate) ? 1 : -1;
        }

        return candidate;
    }
}

 2. 判断是否连续

(参考 228.Summary Ranges

class Solution {
    public List<String> summaryRanges(int[] nums) {
        List<String> res = new ArrayList<>();
        // 判断连续还是不连续的算法
        int i = 0;
        while(i < nums.length){
            int start = i;
            while(i < nums.length-1 && nums[i+1] == nums[i] + 1){
                i++;
            }
            if(nums[start] == nums[i]){
                res.add(nums[i] + "");
            }else{
                res.add(nums[start] + "->" + nums[i]);
            }
            i++;
        }

        return res;
    }
}

 3. intervals merge (57. Insert Interval) 

class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> res = new ArrayList<>();
        int n = intervals.length;
        if(n == 1) return intervals;
        Arrays.sort(intervals,(a,b)->a[0]-b[0]);
        int i = 0;
        while(i<n){
            int[] curr = intervals[i];
            while(i<n-1 && overLap(curr,intervals[i+1])){
                curr = merge(curr,intervals[i+1]);
                i++;
            }   
            res.add(curr);
            i++;

        } 

        return res.toArray(new int[res.size()][]);
    }

    public boolean overLap(int[] curr, int[] next){
        return (curr[1] >= next[0]);
    }

    public int[] merge(int[] curr, int[] next){
        return new int[]{Math.min(curr[0],next[0]), Math.max(curr[1],next[1])  };
    }
}
 

 

 4. 判断是否存在circle:1 - 0 - 2- 3- 1

 (207. Course Schedule
class Solution {
    static int WHITE = 1;
    static int GRAY = 2;
    static int BLACK = 3;

    boolean isPossible;
    Map<Integer,List<Integer>> map;
    List<Integer> topolst;
    Map<Integer,Integer> color;

    public void init(int numCourses, int[][] prerequisites){
        this.isPossible = true;
        this.topolst = new ArrayList<>();
        this.color = new HashMap<>();
        this.map = new HashMap<>();
        for(int i = 0;i<prerequisites.length;i++){
            List<Integer> lst = map.getOrDefault(prerequisites[i][1],new ArrayList<>());
            lst.add(prerequisites[i][0]);
            map.put(prerequisites[i][1],lst);//
        }
        for(int i = 0; i<numCourses; i++ ){
            color.put(i,WHITE);
        } 
    }

    public void dfs(int i){
        if(!this.isPossible) return;
        color.put(i,GRAY);
        if(map.containsKey(i)){
             for(Integer neighbor: map.get(i)){
                 if(color.get(neighbor) == GRAY){ //
                     this.isPossible = false;
                 }
                 if(color.get(neighbor) == WHITE){ //
                     dfs(neighbor);
                 }
            }
        }
        topolst.add(0,i); // 
        color.put(i,BLACK);
    }

    public int[] findOrder(int numCourses, int[][] prerequisites) {
        init(numCourses,prerequisites);     
        for(int i = 0; i<numCourses; i++ ){
            if(color.get(i) == WHITE){
                dfs(i);
            }
        }
        return isPossible ? topolst.stream().mapToInt(i->i).toArray() : new int[0];
    }
}

 5. Graph - shortest path

<1> BFS

 BFS can only be used to find shortest path in a graph if:

  1. There are no loops

  2. All edges have same weight or no weight.

 <2> Dijastra
However, if the graph is more complex, containing weighted edges and loops, then we need a more sophisticated version of BFS, i.e. Dijkstra's algorithm.
PriorityQueue<Integer[]> queue = new PriorityQueue<Integer[]>((a,b)->a[1].compareTo(b[1]));
 
5-2. Dijastra [743. Network Delay Time]
TC: E is the number of edges , N is the number of vertices
pq insertion: pq里面新新旧旧的加在一起 can hold E, E at most N * N-1 => insertion takes O(logN)
=> total is N + ElogN
SC: E + N => constructing vertex-edge map costs E
class Solution {
    class Cell{
    Integer val;
    Integer dist;

    public Cell(Integer val, Integer dist){
        this.val = val;
        this.dist = dist;
    }
    }
    public int networkDelayTime(int[][] times, int n, int k) {
        Map<Integer,List<Cell>> map = new HashMap<>();
     // this is directed graph, if undirected also put time[i][1]
for(int i = 0; i<times.length; i++){ if(!map.containsKey(times[i][0])){ map.put(times[i][0],new ArrayList<>()); } map.get(times[i][0]).add(new Cell(times[i][1],times[i][2])); } // boolean[] seen = new boolean[n+1]; dont need int[] dist = new int[n+1]; Arrays.fill(dist,Integer.MAX_VALUE); dist[k] = 0; PriorityQueue<Cell> q = new PriorityQueue<Cell>((a,b) -> a.dist.compareTo(b.dist)); // get the smallest one q.add(new Cell(k,0)); while(!q.isEmpty()){ Cell curr = q.remove(); // seen[curr.val] = true; if(dist[curr.val] != curr.dist){ // 旧的不管了 continue; } if(!map.containsKey(curr.val)) continue; for(Cell next : map.get(curr.val)){ // if(seen[next.val]) continue; if(curr.dist + next.dist < dist[next.val]){ // update dist[next.val] = curr.dist + next.dist; q.add(new Cell(next.val,dist[next.val])); } } } int max = -1; for(int i = 1; i<=n ; i++){ if(i == k) continue; if(max < dist[i]) max = dist[i]; } return max == Integer.MAX_VALUE ? -1 : max; } }

 

 

6. 有向的用dfs,无向的用bfs

如果要start from 每一个顶点,需要用edge建造int[][]储存点与点之间累计最小的长度
<Find the City With the Smallest Number of Neighbors at a Threshold Distance>
 int[][] mat = new int[n][n];
        for(int i=0; i <n ; i++){
            for(int j =0; j< n ; j++){
                if(i==j)
                    mat[i][j] = 0;
                mat[i][j] = 100001;
            }
        }
        for(int[] edge : edges){
            mat[edge[0]][edge[1]] = edge[2];
            mat[edge[1]][edge[0]] = edge[2];
        }
        for(int x =0; x< n ; x++){
            for(int i =0; i < n ; i++){
                for(int j =0; j < n ; j++){
                    mat[i][j] = Math.min(mat[i][j], mat[i][x] + mat[x][j]);
                }
            }
        }

 7. Trie (prefix tree)

<reference: https://www.geeksforgeeks.org/trie-insert-and-search/>

class Trie {
    class TrieNode{
         TrieNode[] children = new TrieNode[26];
         boolean isEnd;

         public TrieNode(){
                this.isEnd = false;
                for(int i = 0; i<26; i++){
                    children[i] = null;
                }
         }
    }

    TrieNode root;
   
    public Trie() {
       this.root = new TrieNode();
    }
    
    public void insert(String word) {
        char[] arr = word.toCharArray();
        TrieNode curr = root; // this is important
        for(char c : arr){
            if(curr.children[c - 'a'] == null){
                curr.children[c - 'a'] = new TrieNode();
            }
            curr =  curr.children[c - 'a'];
        }
        curr.isEnd = true;
    }
    
    public boolean search(String word) {
        char[] arr = word.toCharArray();
        TrieNode curr = root;
        for(char c : arr){
            if(curr.children[c - 'a'] == null){
                return false;
            }
            curr =  curr.children[c - 'a'];
        }
        return curr.isEnd;
    }
    
    public boolean startsWith(String prefix) {
        char[] arr = prefix.toCharArray();
        TrieNode curr = root;
        for(char c : arr){
            if(curr.children[c - 'a'] == null){
                return false;
            }
            curr =  curr.children[c - 'a'];
        }
        return true;
    }
}

/**
 * Your Trie object will be instantiated and called as such:
 * Trie obj = new Trie();
 * obj.insert(word);
 * boolean param_2 = obj.search(word);
 * boolean param_3 = obj.startsWith(prefix);
 */

 8. frequency majority

指超过n/2)不用 hashmap 而用count

class Solution {
    public int majorityElement(int[] nums) {
        int count = 0;
        int candidate = 0;
        for(int num : nums){
            if(count == 0){
                candidate = num;
            }
            count += num == candidate ? 1:-1;
        }
        return candidate;
    }
}

 9. ArrayList

当我要在arraylist中特定的index remove,同时保持其他所有的index不变

=> index 对应的value和last element交换,然后remove last element

10. rotate the matrix 

1. 左上 和 左下 row 和 col 互换;左上和右下 row 和 col是对应的

2. 从左上来看,row 移动两格(n/2),col移动3格(n/2 + n%2);

implement:

class Solution {
    // j i  ;  i,n-1-j
    // n-1-i j ; n-1-j n-1-i
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        for(int i = 0; i< n/2 + n%2; i++){
            for(int j = 0; j< n/2; j++){  
                int temp = matrix[n-1-i][j];
                matrix[n-1-i][j] = matrix[n-1-j][n-1-i];
                matrix[n-1-j][n-1-i] = matrix[i][n-1-j];
                matrix[i][n-1-j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
}

 11. linkedlist

如果要实现queue中任意一个位置pop(), use Map<Integer,LinkNode>

ListNode has prev & next

12. tree

BST property: in-order traversal can guarantee sorted sequence

13. graph

verticle - edge 

dont understand why time complexity is O(N+M) verticles + edges

 14. 棋盘如何用表示: label -> row & col 

        int n = board.length;
        Pair<Integer,Integer>[] pair = new Pair[n * n + 1];
        Integer[] cols = new Integer[n];
        for(int i = 0; i<n; i++){
            cols[i] = i;
        }
        int label = 1;
        for(int r = n-1; r>=0; r--){
            for(int c : cols){
                pair[label++] = new Pair<Integer,Integer>(r,c);
            }
            Collections.reverse(Arrays.asList(cols)); // ***
        }

 15. 2D coordinate

 l = 0; r = rows * cols - 1;

mid = (l+r)/2; get the index

then

row = mid / cols;

col = mid % col;

16. 最大公约数 

// greatest common divisor
class Solution {
    // 1. greatest common divisor
    // 6 4 -> 2
    public int gcd(int a, int b){ // do not need to care which one is larger
        if(b == 0) return a;
        return gcd(b,a%b);
    }

    public String gcdOfStrings(String str1, String str2) {
        if(!(str2 + str1).equals(str1+str2) ) return "";
        return str1.substring(0,gcd(str1.length(),str2.length()));

    }
    
}

 17. cal the profit

left[i]:  from l to r, <= i day sell, the maximum profit 

right[i]:  from r to l, >= i day buy, the maximum profit 

        int Lmin = prices[0]; int Rmax = prices[n-1]; 
        int LmaxDiff = 0; int RmaxDiff = 0;
        for(int i = 1; i<n; i++){
            LmaxDiff = Math.max(LmaxDiff,prices[i]-Lmin); // record the maxDiff, not the max; 否则:下降?
            left[i] = LmaxDiff;
            Lmin = Math.min(Lmin,prices[i]); // record the min, we need to know the min of the past

            int j = n-1-i;
            RmaxDiff = Math.max(RmaxDiff,Rmax-prices[j]);
            right[j] = RmaxDiff;
            Rmax = Math.max(Rmax,prices[j]); // record the max, need to know the max in the future
        }  

 

 

 
 
posted @ 2023-07-06 02:05  PEAR2020  阅读(5)  评论(0编辑  收藏  举报