leetcode 刷题笔记二

leetcode 102. Binary Tree Level Order Traversal
  1. 给出二叉树后,给出它的层次遍历结果,类似于BFS广度优先搜索
  2. 用Queue保存当前层的节点,对Queue中的节点遍历获得下一层的节点
  3. 补充解释一下Java中的queue,Queue是接口,与List、Set同一级别,都继承了Collection接口,LinkedList实现了Queue接口,Queue接口缩小了对LinkedList方法的访问,只能访问LinkedList中的Queue方法。还有多个阻塞队列如LinkedBlockingQueue, ArrayBlockingQueue, PriorityBlockingQueue,DelayQueue

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result =new ArrayList<List<Integer>>();
        TreeNode cur =root;
        if(cur==null) return result;
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(cur);
        while(!queue.isEmpty()){
            List<Integer> list = new ArrayList<Integer>();
            Queue<TreeNode> tqueue = new LinkedList<TreeNode>();
            for(TreeNode node:queue){
                list.add(node.val);
                if(null != node.left) tqueue.add(node.left);
                if(null != node.right) tqueue.add(node.right);
            }
            queue=tqueue;
            result.add(new ArrayList<Integer>(list));
        }
        return result;
    }
leetcode 114. Flatten Binary Tree to Linked List
  1. 题目意思:将二叉树进行前序遍历,然后以左子树为null的情况构建新的二叉树
  2. 思路:将当前节点的右子树移到当前节点左子树的最右子树下,然后将左子树移到右子树。

    public void flatten(TreeNode root) {
       if(root == null) return ;
        TreeNode temp = root;
        TreeNode cur = root;
        while(cur!=null){
            if(cur.left!=null){
                temp = cur.left;
                while(temp.right!=null) temp =temp.right;
                temp.right = cur.right;
                cur.right = cur.left;
                cur.left = null;
            }
            cur = cur.right;
        }
    }
leetcode 139. Word Break 动态规划
  1. 给出一个字符串和一个字符串字典,若该字符串可以由字典中的字符串组成,则返回true,否则返回false
  2. 定义一个跟字符串长度相同的boolean 数组,当dp[i]==true并且list.contains(s.subString(i,j)),则dp[j]为true
  3. 根据规则,将数组进行遍历,获得所有的值,结果返回dp[s.length];

    public boolean wordBreak(String s, List<String> wordDict) {
        if(null == s || s.length()==0) return false;
        boolean [] dp =new boolean[s.length()+1];
        dp[0]=true;
        for(int i=1;i<dp.length;i++){
            for(int j=0;j<i;j++){
                if(dp[j]== true && wordDict.contains(s.substring(j,i))){
                    dp[i]=true;
                }
            }
        }
        return dp[s.length()];
    }
leetcode 142. Linked List Cycle II 快慢指针判断是否有环
  1. 给出一个链表,判断是否有环,如果有则返回环的节点
  2. 思路:设置快慢两个指针,快指针每次走2步,慢指针每次走1步,如果快慢指针重合,则存在环。当出现环时,将慢指针变成开始位置,快指针每次变成只走一步,当快慢指针再一次重合的地方就是环的节点

    public ListNode detectCycle( ListNode head ) {
       if(head ==null || head.next == null) return null;
        ListNode sNode = head;
        ListNode fNode = head;
        while(fNode!=null&&fNode.next!=null){
            sNode = sNode.next;
            fNode = fNode.next.next;
            if(sNode == fNode){
                break;
            }
        }
        if(fNode == null || fNode.next==null) return null;
        sNode = head;
        while(fNode!=sNode){
            fNode = fNode.next;
            sNode = sNode.next;
        }
        return fNode;
    }
leetcode 200. Number of Islands 深度或广度算法
  1. 题目的意思:给一个二维数组,1代表陆地,0代表水,找出地图中陆地的个数
  2. 思路:遍历数组,如果值为1,把自身置为0,然后将与它相邻的1全部改成0,同时陆地个数加1

    public int numIslands(char[][] grid) {
        int num=0;
        if(grid==null || grid.length==0) return num;
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                if(grid[i][j]=='1'){
                    helper(grid,j,i);
                    num++;
                }
            }
        }
        return num;
    }
    public void helper(char[][] grid,int col,int row){
        if(row<0||row>=grid.length||col<0||col>=grid[0].length||grid[row][col]!='1') return;
        grid[row][col]='0';
        helper(grid,col-1,row);
        helper(grid,col,row-1);
        helper(grid,col+1,row);
        helper(grid,col,row+1);
    
    }
leetcode 207. Course Schedule 图的临近表表示(可以再刷一次)
  1. 题目意思:给出0-(n-1)的课程和课程的前后关系,判断是否有环出现,[1,0]指学习课程1之前需要学课程0.
  2. 思路:用临界表的结构存储,List 来存储每门课程学习后才可以学的课程名。然后定义一个数组,存储每门课程需要先学的课程数目。每次找到入度为0的节点,然后将该节点与其它节点的关联去掉,重复该步骤,如果能依次去掉所有课程,则不存在环,否则则有环出现

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<Set<Integer>> grap = new ArrayList<Set<Integer>>();
        for(int i=0;i<numCourses;i++){
            Set<Integer> set = new HashSet<Integer>();
            grap.add(set);
        }
        for(int i=0;i<prerequisites.length;i++){
            grap.get(prerequisites[i][1]).add(prerequisites[i][0]);
        }
        int [] preNums =new int[numCourses];
        for(int i=0;i<numCourses;i++){
            Set<Integer> set =grap.get(i);
            Iterator<Integer> iterator = set.iterator();
            while (iterator.hasNext()){
                preNums[iterator.next()]++;
            }
        }
        for(int i=0;i<numCourses;i++){
            int j=0;
            for(;j<numCourses;j++){
                if(preNums[j]==0) break;
            }
            if(j==numCourses) return false;
            preNums[j]=-1;
            Set<Integer> set = grap.get(j);
            Iterator<Integer> iterator = set.iterator();
            while(iterator.hasNext()){
                preNums[iterator.next()]--;
            }
        }
        return true;
    }
leetcode 208. Implement Trie (Prefix Tree) 字典树结构定义
  1. 题目意思是构造一个prefix树,前序树或字典树
  2. 思路:要先定义树的节点,数据节点需要包括当前节点的值,节点的子节点,因为一共有26个英文字母,因此子节点设置为一个长度为26的char数组比较合适,设置一个是否为叶子节点的标识符。同时需要有节点插入,判断是非存在某个子节点的方法

    class Trie {
    
    class TrieNode {
        private char var;
        private TrieNode [] childs;
        private   boolean isEnd;
        public TrieNode(){
            childs = new TrieNode[26];
        }
        public boolean containkey(char ch){
            if(childs[ch-'a']!=null) return true;
            else return false;
        }
    
        public TrieNode get(char ch){
            return childs[ch-'a'];
        }
    
        public void put(char ch, TrieNode node){
            childs[ch-'a']=node;
        }
    
        public void setEnd(){
            isEnd = true;
        }
    
        public boolean isEnd(){
            return isEnd;
        }
    
    }
    
    private TrieNode root;
    /** Initialize your data structure here. */
    public Trie() {
        root = new TrieNode();
    
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        TrieNode temp = root;
        for(int i=0;i<word.length();i++){
            if(!temp.containkey(word.charAt(i))){
                temp.put(word.charAt(i),new TrieNode());
            }
            temp = temp.get(word.charAt(i));
        }
        temp.setEnd();
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
       TrieNode result =searchPrefixNode(word);
        if(result!=null && result.isEnd()) return true;
        else  return false;
    }
    
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TrieNode result = searchPrefixNode(prefix);
        return result!=null;
    }
    
    public TrieNode searchPrefixNode(String prefix){
        TrieNode temp = root;
        for(int i=0;i<prefix.length();i++){
            if(temp.containkey(prefix.charAt(i))){
                temp = temp.get(prefix.charAt(i));
            }else{
                return null;
            }
        }
        return temp;
    }
    }
leetcode 338. Counting Bits
  1. 题目意思:给一个数字n,写出0到n的所有数字二进制表示的1的个数
  2. 方法很多:暴力破解法:求出每个数字的二进制,然后计算位数;运行c++中自带的函数;找规律:规律1:当前num[i]=num[i&(i-1)]+1; 规律2:i为偶数时 num[i] =num[i/2],i为奇数时,num[i]=num[i/2]+1;
  3. 规律1代码如下: i&i-1 可以用来判断i是否为2的指数

    public int[] countBits(int num) {
        int [] temp =new int[num+1];
        temp[0] =0;
        for(int i=1;i<=num;i++){
            temp[i]=temp[i&(i-1)]+1;
        }
        return temp;
    }
  4. 规律2 代码如下:

    public int[] countBits(int num) {
        int [] temp =new int[num+1];
        temp[0] =0;
        for(int i=1;i<=num;i++){
            if(i%2 ==0) temp[i]=temp[i/2];
            else temp[i]=temp[i/2]+1;
        }
        return temp;
    }
leetcode 406. Queue Reconstruction by Height
  1. 题目意思:[h,k]中h是人的身高,k是当前人前面有多少比他高的,重新排一下队列
  2. 思路:首先按照身高进行降序排列,如果身高相同,则按照k升序排列。然后按照重新排列起来的顺序,放到序列对应的位置,因为排序后,始终能保证插入的位置前面人的身高比自己高。

    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if(o1[0]!=o2[0]) return o2[0]-o1[0];
                else return o1[1]-o2[1];
            }
        });
        List<int[]> res =new LinkedList<int []>();
        for(int [] p: people){
            res.add(p[1],p);
        }
        return res.toArray(new int[people.length][]);
    }
leetcode 347. Top K Frequent Elements
  1. 题目意思:求出序列中出现频率较高的前k个元素
  2. 思路:用Map统计每个元素个数,然后对map按值排序后,取出前k个。不难,注意一下map的按值排序方法

    List<Map.Entry<Integer,Integer>> list =new ArrayList<Map.Entry<Integer, Integer>>(map.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o2.getValue()-o1.getValue();
            }
        });
leetcode. 547. Friend Circles (并查集或者连通工程)
  1. 给出n个点,用二维数组表示点与点之间是否关联,求形成的团的个数(类似于连同工程)
  2. 并查集:用一维数组parents[n]表示对应点的父节点,rank[n]表示每个节点的级别,从而形成树状结构。该结构中有两个函数,一个是find找某个节点的根节点,另一个函数是集合合并,union(i,j)根据找i,j的根节点,如果不相等,则根据根节点的层级关系,将一个节点赋值给另一个节点的父节点,同时将非联通区块的个数减1

    class UnionFound{
        private int count;
        private int [] pre;
        private int [] rank;
        public UnionFound(int n){
            count = n ;
            pre = new int [n];
            rank = new int [n];
            for(int i=0;i<n;i++){
                pre[i] =i;
            }
        }
        public int findParent(int p){
            while(p != pre[p]){
                p =pre[p];
            }
            return p;
        }
        public void union(int p,int q){
            int prep =findParent(p);
            int preq = findParent(q);
            if(prep == preq) return;
            if(rank[prep]>rank[preq]){
                pre[preq] = prep;
            }else{
                pre[prep] = preq;
                if(rank[prep]==rank[preq]){
                    rank[preq]++;
                }
            }
            count--;
        }
    
        public int getCount(){
            return count;
        }
    }  
    public int findCircleNum(int [][] matri){
        int n =matri.length;
        UnionFound uf = new UnionFound(n);
        for(int i=0;i<n-1;i++){
            for(int j=i;j<n;j++){
                if(matri[i][j]==1) uf.union(i,j);
            }
        }
        return uf.count;
    }
leetcode.309. Best Time to Buy and Sell Stock with Cooldown 动态规划
  1. 题目意思:给出股票每天的价格,每天可以买,卖和不操作。卖之后的一天不能做任何操作,算最大利润
  2. 根据当天是否有股票进行划分,如果当天有股票,则可能是昨天的卖多股票-今天买的股票,或今天和昨天一样。如果当天没有股票,则可能是昨天买的股票+今天价格,或昨天卖出股票。

    public int maxProfit(int[] prices) {
        int pre_sell=0, pre_buy =0, sell=0,buy=Integer.MIN_VALUE;
        for(int i: prices){
            pre_buy =buy;
            buy =Math.max(pre_buy,pre_sell-i);
            pre_sell = sell;
            sell =Math.max(pre_sell,pre_buy+i);
        }
        return sell;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值