經過兩場大廠面試,面了四道算法題目,發現自己菜到連數據結構最基本的一些算法題目都無法快速寫下來,這些基礎題目延申出來的題目,簡單到上去就基本有思路,但是在面試的時候,依然無法快速地把代碼寫出來。痛心疾首,有了這篇博文。
基礎題目,5~10分鐘,完成代碼是最基本的能力
(題號是力扣的題號)
144:二叉樹的前序遍歷
//遞歸
public List<Integer> preorderTraversal1(TreeNode root) {
List<Integer> list = new LinkedList<Integer>();
if(root == null ) return list;
return preorderTraversalHelp(root,list);
}
public List<Integer> preorderTraversalHelp(TreeNode root,List<Integer> list){
if(root == null ) return list;
list.add(root.val);
preorderTraversalHelp(root.left,list);
preorderTraversalHelp(root.right,list);
return list;
}
//迭代
public List<Integer> preorderTraversal2(TreeNode root) {
LinkedList<Integer> list = new LinkedList<>();
LinkedList<TreeNode> stack= new LinkedList<>();
if(root == null ) return list;
stack.add(root);//入棧順序爲--根,出棧list保存,右左孩子入棧,最終求得前序--根左右
while(!stack.isEmpty()) {
TreeNode node =stack.removeLast();
list.add(node.val);
if(node.right !=null)
stack.add(node.right);
if(node.left !=null)
stack.add(node.left);
}
return list;
}
145:二叉樹的後序遍歷
遞歸基本一樣,就不再貼代碼了
//迭代
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<Integer> list = new LinkedList<Integer>();
LinkedList<TreeNode> stack= new LinkedList<>();
if(root == null ) return list;
stack.add(root);//入棧順序爲--根,出棧list保存,左右孩子入棧,右左孩子出棧,list逆序保存,最終求得--左右根
while(!stack.isEmpty()) {
TreeNode node =stack.pollLast();
list.addFirst(node.val); //前序遍歷代碼區別處1
if(node.left !=null) //前序遍歷代碼區別處2
stack.add(node.left);
if(node.right !=null) //前序遍歷代碼區別處3
stack.add(node.right);
}
return list;
}
94:二叉樹的中序遍歷
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res= new LinkedList<Integer>();
LinkedList<TreeNode> stack= new LinkedList<TreeNode>();
while (true) {
while (root !=null) {
stack.add(root);
root= root.left;
}
if(stack.isEmpty()) return res;
root = stack.removeLast();
res.add(root.val);
root=root.right;
}
}
二叉搜索樹,基本都是中序相關的變形題目
中序變形1---------230:二叉搜索樹中第K小的元素
這道題目顯然就是中序的變形
public int kthSmallest(TreeNode root, int k) {
if(root == null )return -1;
LinkedList<Integer> list = new LinkedList<Integer>();
order(root, list);
return list.get(k-1);
}
public LinkedList<Integer> order(TreeNode root,LinkedList<Integer> list) {
if(root == null ) return list;
order(root.left, list);
list.add(root.val);
order(root.right, list);
return list;
}
//用棧優化
public int kthSmallest(TreeNode root, int k) {
if(root == null )return -1;
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
while (true) {
while (root !=null) {//while (root !=null)完成根左的入棧
stack.add(root);
root= root.left;
}
root = stack.removeLast();
if(--k!=0) root=root.right;//每次出棧--k,當出棧到第K個元素的時候,return root.val
else {
return root.val;
}
}
}
中序變形2---------108.將有序數組轉換爲二叉搜索樹
public TreeNode sortedArrayToBST(int[] nums) {
if(nums == null) {
return null;
}
return helper(nums, 0, nums.length-1);
}
//找根
public TreeNode helper(int[] nums,int left,int right) {
if(left>right) {
return null;
}
int mid = (left+right)/2;
TreeNode current = new TreeNode(nums[mid]);
current.left = helper(nums, left, mid-1);
current.right = helper(nums, mid+1, right);
return current;
}
中序變形3--------109.有序鏈表轉換二叉搜索樹
快慢指針找中點
public TreeNode sortedListToBST(ListNode head) {
if(head == null)return null;
return help(head, null);
}
public TreeNode help(ListNode head,ListNode tail){
if(head == tail || head ==null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
while(fast.next!= tail&& fast.next.next !=tail) {
fast = fast.next.next;
slow = slow.next;
}
TreeNode treeNode = new TreeNode(slow.val);
treeNode.left = help(head, slow);
treeNode.right = help(slow.next, tail);
return treeNode;
}
中序變形4--------98:驗證二叉搜索樹
這個題目用中序遞歸,效率很低,但是自建棧,可以優化
//中序遞歸
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
LinkedList<Integer> list = new LinkedList<Integer>();
inOrder(root, list);
for(int i =0;i<list.size()-1;i++) {
if(list.get(i)>=list.get(i+1))
return false;
}
return true;
}
public List<Integer> inOrder(TreeNode root,LinkedList<Integer> list){
if(root == null) return list;
inOrder(root.left, list);
list.add(root.val);
inOrder(root.right, list);
return list;
}
//中序迭代
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
LinkedList<Integer> list = new LinkedList<Integer>();
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
while(true) {
int s =0;
while(root!=null) {
stack.add(root);
root = root.left;
}
if(!stack.isEmpty()) {
break;
}
root = stack.removeLast();
if(s ==0) {
list.add(root.val);
s++;
}else if(root.val<= list.getLast()) {
return false;
}else{
list.add(root.val);
root=root.right;
}
}
return true;
}
//普通遞歸
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isValidBST(TreeNode root, long minVal, long maxVal) {
if(root == null)
return true;
if(root.val >= maxVal || root.val <= minVal)
return false;
return isValidBST(root.left, minVal, root.val)&&isValidBST(root.right, root.val, maxVal);
}
107.二叉樹的層次遍歷II(逆序輸出)
這個題目跟層次遍歷沒什麼區別,就是注意下是逆序輸出就行
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> list=new LinkedList<List<Integer>>();
if(root == null)
return list;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
int size = queue.size();//記錄當前層的結點個數,並保存再curList
LinkedList<Integer> curList = new LinkedList<Integer>();
while(size>0) {
TreeNode curNode = queue.pollFirst();
if(curNode.left!=null) {
queue.add(curNode.left);
}
if(curNode.right!=null) {
queue.add(curNode.right);
}
curList.add(curNode.val);
size--;
}
list.add(0,curList);//不逆序的話就是list.add(curList);
}
return list;
}
110:平衡二叉樹
//判斷平衡=>遞歸求解二叉樹的高度
public boolean isBalanced(TreeNode root) {
return getHeight(root)!=Integer.MAX_VALUE;
}
public int getHeight(TreeNode root) {
if(root == null) return 0;
int left = getHeight(root.left);
if(left == Integer.MAX_VALUE)
return Integer.MAX_VALUE;
int right = getHeight(root.right);
if(right == Integer.MAX_VALUE)
return Integer.MAX_VALUE;
if(Math.abs(left-right)>1) {
return Integer.MAX_VALUE;
}
return Math.max(left,right)+1;
}