leetcode 144 145 二叉樹的遍歷 141 142 環狀連結串列 149 窮舉法
阿新 • • 發佈:2018-12-11
[144] binary-tree-preorder-traversal 二叉樹的前序遍歷
使用棧,不用遞迴
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ import java.util.*; public class Solution { public ArrayList<Integer> preorderTraversal(TreeNode root) { ArrayList<Integer> preorder = new ArrayList<Integer>(); if(root == null) return preorder; Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(root); while(!stack.isEmpty()){ TreeNode node = stack.pop(); preorder.add(node.val); if(node.right != null) stack.push(node.right); if(node.left != null) stack.push(node.left); } return preorder; } }
[145] binary-tree-postorder-traversal 二叉樹的後續遍歷
同樣是使用棧,這麼做會改變二叉樹的結構,如果不想改變,需要額外記憶體用來將二叉樹複製一份。
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ import java.util.*; public class Solution { public ArrayList<Integer> postorderTraversal(TreeNode root) { ArrayList<Integer> postorder = new ArrayList<Integer>(); if(root == null) return postorder; Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(root); while(!stack.isEmpty()){ TreeNode node = stack.peek(); if(node.left == null && node.right == null) { stack.pop(); postorder.add(node.val); } if(node.right != null) stack.push(node.right); if(node.left != null) stack.push(node.left); node.left = null; node.right = null; } return postorder; } }
[141] linked-list-cycle
快慢指標相遇則有環,快指標能變成null則無環。
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { if(head == null) return false; ListNode fast = head; ListNode slow = head; while(fast.next != null && fast.next.next != null){ fast = fast.next.next; slow = slow.next; if(fast == slow) return true; } return false; } }
[142] linked-list-cycle-ii
有如下結論:
a從快慢指標相遇的點出發每次走一步,b從頭出發每次走一步,a,b會在環開始的節點相遇。
由此則得程式碼如下
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null) return null;
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
ListNode head1 = head;
while(head1 != slow){
head1 = head1.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
}
[149] max-points-on-a-line 窮舉法
這道題普遍有兩種做法,一種是先取出兩個點組成一條直線,再檢測其餘的點有多少個在這條直線上,找出最大的那條直線,由於巢狀三層迴圈,演算法的時間複雜度為O(n^3)。程式碼很好實現。且可以用乘法判斷是否共線,因此不會出現由於浮點數的精度問題導致的不準確情況。
另一種是先選取一個點作為基點,然後計算其餘各點與這個點確定的斜率,斜率相同則視為在同一條直線上,維護一個map,鍵值對為 斜率-點的個數。但是在計算斜率時,由於精度問題,有可能會出現及其相似但不相同的斜率無法辨別的情況。
比如輸入:[[0,0],[94911151,94911150],[94911152,94911151]] ,則無法辨別從而導致認為三點共線。
第二種演算法實現:(leetcode無法通過,牛客網可以通過)
import java.util.*;
public class Solution {
public int maxPoints(Point[] points) {
if(points.length < 3) return points.length;
int a,b,x,y;
double k;
int max = 1;
for (int j = 0; j < points.length ; j++) {
a = points[j].x;
b = points[j].y;
int same =0;
Map<Double,Integer> map = new HashMap<Double,Integer>();
for(int i = 0;i < points.length;i++){
if(i == j) continue;
x = points[i].x;
y = points[i].y;
if(a == x && b == y) {
same ++;
continue;
};
if(a == x) k = Integer.MAX_VALUE;
else if(b == y) k = 0;
else k = (double)(y - b)/(double)(x - a);
if(map.containsKey(k)) map.put(k,map.get(k) + 1);
else map.put(k,2);
}
int temp = 1;
for(Integer value : map.values()){
temp = Math.max(temp,value);
}
max = Math.max(temp + same,max);
}
return max;
}
}