leetcode 102. Binary Tree Level Order Traversal
- 给出二叉树后,给出它的层次遍历结果,类似于BFS广度优先搜索
- 用Queue保存当前层的节点,对Queue中的节点遍历获得下一层的节点
补充解释一下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
- 题目意思:将二叉树进行前序遍历,然后以左子树为null的情况构建新的二叉树
思路:将当前节点的右子树移到当前节点左子树的最右子树下,然后将左子树移到右子树。
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 动态规划
- 给出一个字符串和一个字符串字典,若该字符串可以由字典中的字符串组成,则返回true,否则返回false
- 定义一个跟字符串长度相同的boolean 数组,当dp[i]==true并且list.contains(s.subString(i,j)),则dp[j]为true
根据规则,将数组进行遍历,获得所有的值,结果返回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 快慢指针判断是否有环
- 给出一个链表,判断是否有环,如果有则返回环的节点
思路:设置快慢两个指针,快指针每次走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代表陆地,0代表水,找出地图中陆地的个数
思路:遍历数组,如果值为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 图的临近表表示(可以再刷一次)
- 题目意思:给出0-(n-1)的课程和课程的前后关系,判断是否有环出现,[1,0]指学习课程1之前需要学课程0.
思路:用临界表的结构存储,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) 字典树结构定义
- 题目意思是构造一个prefix树,前序树或字典树
思路:要先定义树的节点,数据节点需要包括当前节点的值,节点的子节点,因为一共有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
- 题目意思:给一个数字n,写出0到n的所有数字二进制表示的1的个数
- 方法很多:暴力破解法:求出每个数字的二进制,然后计算位数;运行c++中自带的函数;找规律:规律1:当前num[i]=num[i&(i-1)]+1; 规律2:i为偶数时 num[i] =num[i/2],i为奇数时,num[i]=num[i/2]+1;
规律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; }
规律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
- 题目意思:[h,k]中h是人的身高,k是当前人前面有多少比他高的,重新排一下队列
思路:首先按照身高进行降序排列,如果身高相同,则按照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
- 题目意思:求出序列中出现频率较高的前k个元素
思路:用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 (并查集或者连通工程)
- 给出n个点,用二维数组表示点与点之间是否关联,求形成的团的个数(类似于连同工程)
并查集:用一维数组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 动态规划
- 题目意思:给出股票每天的价格,每天可以买,卖和不操作。卖之后的一天不能做任何操作,算最大利润
根据当天是否有股票进行划分,如果当天有股票,则可能是昨天的卖多股票-今天买的股票,或今天和昨天一样。如果当天没有股票,则可能是昨天买的股票+今天价格,或昨天卖出股票。
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; }