Leetcode Easy Collection Top Interview Questions打卡日记

381 阅读17分钟

###############

NumSoFar: 49

###############

  1. Remove Duplicates from Sorted Array

double pointers, one slow one quick to test equal or not.

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums == null || nums.length == 0) return 0;
        if(nums.length == 1) return 1;
        int i = 0, j = 1;
        int len = 1;
    
        while(i < nums.length && j < nums.length){
            if(nums[i] == nums[j]) j++;
            else{
                nums[i+1] = nums[j];
                i++;
                j++;
                len++;
            }
        }
        return len;
    }
}
  1. Two Sum

HashMap

class Solution {
public int[] twoSum(int[] nums, int target) {
    if(nums == null || nums.length == 0) throw new IllegalArgumentException();
    HashMap<Integer, Integer> m = new HashMap<>();
    for(int i = 0; i < nums.length; i++){
        int res = target - nums[i];
        if(m.containsKey(res)) return new int[] {m.get(res), i};
        else
            m.put(nums[i], i);
    }
    throw new IllegalArgumentException();
}
}
  1. FizzBuzz actual question @ Lutron onsite.... datastructure announcement:
class Solution {
public List<String> fizzBuzz(int n) {
    List<String> ls = new ArrayList<>();
    String s = new String();
    for(int i = 1; i <= n; i++){
        if(i % 3 == 0 && i % 5 == 0)
            s = "FizzBuzz";
        else if(i % 3 == 0)
            s = "Fizz";
        else if(i % 5 == 0)
            s = "Buzz";
        else s = Integer.toString(i);
        ls.add(s);
    }
    return ls;
}
}

Details Runtime: 1 ms, faster than 99.90% of Java online submissions for Fizz Buzz. Memory Usage: 37.2 MB, less than 100.00% of Java online submissions for Fizz Buzz.

...idont understand since i am using the simplest way...

  1. Single Number

xor method:

class Solution {
public int singleNumber(int[] nums) {
    int a = 0;
    for(int i = 0; i < nums.length; i++){
        a ^= nums[i];
    }
    return a;
}
}

hashset method(used extra space):

the trick:

Iterator it = s.iterator();
Integer ans = it.next();

will return error because the type in first line of code is wrong.

but:

Iterator<Integer> it = s.iterator();
Integer ans = it.next();

is correct.

class Solution {
public int singleNumber(int[] nums) {
    HashSet<Integer> s = new HashSet<>();
    for(int i = 0; i < nums.length; i++){
        if(s.contains(nums[i])) s.remove(nums[i]);
        else s.add(nums[i]);
    }
    Iterator<Integer> it = s.iterator();
    Integer ans = it.next();
    return ans;
}
}
  1. Merge Two Sorted Lists

    class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2){ if(l1 == null || l2 == null) return l1 == null ? l2 : l1; ListNode dummy = new ListNode(0); ListNode trans = dummy; while(l1 != null || l2 != null){ int v1 = l1 != null ? l1.val : Integer.MAX_VALUE; int v2 = l2 != null ? l2.val : Integer.MAX_VALUE; if(v1 <= v2){ trans.next = l1; trans = trans.next; l1 = l1.next; } else{ trans.next = l2; trans = trans.next; l2 = l2.next; } } return dummy.next; } } class Solution { ListNode dummy = new ListNode(0); public ListNode mergeTwoLists(ListNode l1, ListNode l2){ if(l1 == null || l2 == null) return l1 == null ? l2 : l1; ListNode cur = dummy; merge(cur, l1, l2); return dummy.next;

    } private void merge(ListNode cur, ListNode l1, ListNode l2){ if(l1 == null && l2 == null) return; int v1 = l1 == null ? Integer.MAX_VALUE : l1.val; int v2 = l2 == null ? Integer.MAX_VALUE : l2.val; if(v1 <= v2){ cur.next = l1; cur = cur.next; l1 = l1.next; } else{ cur.next = l2; cur = cur.next; l2 = l2.next; } merge(cur, l1, l2); } }

  2. Contains Duplicate

class Solution {
public boolean containsDuplicate(int[] nums) {
    if(nums == null || nums.length == 0) return false;
    HashSet<Integer> s = new HashSet<>();
    for(int i = 0; i < nums.length; i++){
        if(s.contains(nums[i])) return true;
        else s.add(nums[i]);
    }
    return false;
}
}

result:

Success Details Runtime: 9 ms, faster than 57.49% of Java online submissions for Contains Duplicate. Memory Usage: 43.8 MB, less than 68.10% of Java online submissions for Contains Duplicate.

obviously not the best solution

class Solution {
public boolean containsDuplicate(int[] nums) {
    Set<Integer> s = new HashSet<>();
    for(int i = 0; i < nums.length; i++){
        s.add(nums[i]);
    }
    if(nums.length == s.size()) return false;
    else return true;
}
}

result:

Success Details Runtime: 8 ms, faster than 71.12% of Java online submissions for Contains Duplicate. Memory Usage: 43.1 MB, less than 92.24% of Java online submissions for Contains Duplicate.

much better i guess.

  1. Move Zeros
class Solution {
public void moveZeroes(int[] nums) {
    for(int quick = 0, slow = 0; quick < nums.length; quick++){
        if(nums[quick] != 0){
            int temp = nums[slow];
            nums[slow] = nums[quick];
            nums[quick] = temp;
            slow++;
        }
    }
}
}

two pointers starting with 0, check the number of quick index if it equals to 0 every time. if so, leave slow one not moving, increase the quick only to the next. this ensures that the numbers between index quick and slow are 0s. if quick meets a non-zero number, exchange the number of slow and quick index. this makes sure the non-zero numbers with right order goes to the front. then increase both quick and slow since the slow index number is swapped and is non-zero and the quick is zero.

go unitl the quick reaches the end of the array. all zeros should be in the back and the rest should be in the front with correct order.

  1. Valid Parentheses

    class Solution { public boolean isValid(String s) { Stack stack = new Stack<>(); HashMap<Character, Character> hm = new HashMap<>(); hm.put(')', '('); hm.put(']', '['); hm.put('}', '{'); for(int i = 0; i < s.length(); i++){ if(hm.containsKey(s.charAt(i))){ if(stack.size() == 0 || stack.peek() != hm.get(s.charAt(i))) return false; else stack.pop(); } else stack.push(s.charAt(i)); } return stack.isEmpty(); } }

  2. Best Time to Buy and Sell Stock II

class Solution{
    public int maxProfit(int[] prices) {
        int maxProfit = 0;
        for(int i = 1; i < prices.length; i++){
            if(prices[i] > prices[i-1]){
                maxProfit += prices[i] - prices[i-1];
            }
        }
        return maxProfit;
        
    }
}
  1. Rotate Array

basic idea:

reverse all numbers

reverse first k numbers

reverse last n-k numbers

note that when k > the length of array, rotating k times is the same as rotating k % n times

class Solution {
public void rotate(int[] nums, int k) {
    int n = nums.length;
    if(n == 0 || n == 1) return;
    int valid_k = k > n ? k % n : k;
    reverse(nums, 0, n-1);
    reverse(nums, 0, valid_k-1);
    reverse(nums, valid_k, n-1);
}
public void reverse(int[] nums, int start, int end){
    while(start < end){
        int temp = nums[start];
        nums[start] = nums[end];
        nums[end] = temp;
        start++;
        end--;
    }
}
}

result: Success Details Runtime: 0 ms, faster than 100.00% of Java online submissions for Rotate Array. Memory Usage: 37.2 MB, less than 100.00% of Java online submissions for Rotate Array.

  1. Intersection of Two Arrays II
class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        List<Integer> l = new ArrayList<>();
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int p1 = 0, p2 = 0;
        while(p1 < nums1.length && p2 < nums2.length){
            if(nums1[p1] < nums2[p2]) p1++;
            else if(nums1[p1] > nums2[p2]) p2++;
            else{
                l.add(nums1[p1++]);
                p2++;
            }
        }
        int[] ans = new int[l.size()];
        for(int i = 0; i < ans.length; i++){
            ans[i] = l.get(i);
        }
        return ans;
    }
}
  1. Plus One

    class Solution { public int[] plusOne(int[] digits) { for(int i = digits.length-1; i >= 0; i--){ digits[i]++; //add last, if carry then add next digits[i] %= 10; //if carry, then 0, other case remain the same if(digits[i] != 0) return digits; //no carry, then return; else loop to add next } //if all looped and still get carry, then must be all 9 //return an array with original length +1 digits = new int[digits.length+1]; digits[0] = 1; return digits; } }

  2. Valid Sudoku

some math tricks on calculating index, how to declare a HashSet array, and in the wrong way by adding element to one HashSet in an array, you get all the HashSets in the array added this element which was a nightmare.

class Solution {
    public boolean isValidSudoku(char[][] board) {
        HashSet[] row = new HashSet[9];
        HashSet[] col = new HashSet[9];
        HashSet[] box = new HashSet[9];
        
        for(int i = 0; i < 9; i++){
            row[i] = new HashSet<Integer>();
            col[i] = new HashSet<Integer>();
            box[i] = new HashSet<Integer>();
        }//tested way to add hashsets
        
        for(int i = 0; i < 9; i++){
            for(int j = 0; j < 9; j++){
                int box_num = i / 3 * 3 + j / 3;
                if(board[i][j] != '.'){
                    int cur = Character.getNumericValue(board[i][j]);
                    if(row[i].contains(cur) || col[j].contains(cur) || box[box_num].contains(cur)) return false;
                    else{
                        row[i].add(cur);
                        col[j].add(cur);
                        box[box_num].add(cur);
                    }
                }
            }
        }
        return true;
    }
}
  1. Rotate Image

Given input matrix = [ [1,2,3], [4,5,6], [7,8,9] ],

rotate the input matrix in-place such that it becomes: [ [7,4,1], [8,5,2], [9,6,3] ]

not hard to assume that in order to rotate it, we:

1.see n by n matrix as a n dimension matrix 2.reverse this n-d matrix 3.mirror the new n by n matrix by diagnol line

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        int first = 0, last = n-1;
        while(first < last){
            int[] temp = matrix[first];
            matrix[first] = matrix[last];
            matrix[last] = temp;
            first++;
            last--;
        }
        //reverse finished
        
        for(int i = 0; i < n; i++){
            for(int j = i+1; j < n; j++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
}
  1. Reverse String

no much to say, two pointers, but a better way to increase/decrease index:

class Solution {
public void reverseString(char[] s) {
    int i = 0, j = s.length-1;
    while(i < j){
        char temp = s[i];
        s[i++] = s[j];
        s[j--] = temp;
    }
}
}
  1. Reverse Integer

when try to separate integer, use more % and /

in this problem, notice the boudary case, and the number won't cross boundary only when they are >Integer.MAX_VALUE /10 || (==Integer.MAX_VALUE && nextdigit > 7) since the 2^31-1 is xxxxxxxxxx7, same for negative number.

class Solution {
public int reverse(int x) {
    int ans = 0;
    while(x != 0){
        int pop = x % 10;
        if(ans > Integer.MAX_VALUE/10 || (ans == Integer.MAX_VALUE/10 && pop > 7)) return 0;
        if(ans < Integer.MIN_VALUE/10 || (ans == Integer.MIN_VALUE/10 && pop < -8)) return 0;
        ans = ans * 10 + pop;
        x /= 10;
    }
    return ans;
}
}
  1. First Unique Character in a String

new method in hashmap .getOrDefault():

hm.getOrDefault(a,b) returns the value of key a in hashmap hm if hm contains key a, else it returns the value of default (but won't put the pair in the hm)

class Solution {
    public int firstUniqChar(String s) {
        HashMap<Character,Integer> hm = new HashMap<>();
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            hm.put(c, hm.getOrDefault(c, 0) + 1);
            //here this line equals to:
            //if(!hm.containsKey(c)) hm.put(c,1);
            //else hm.put(c,hm.get(c)+1);
        }
        for(int i = 0; i < s.length(); i++){
            if(hm.get(s.charAt(i)) == 1) return i;
            //since we iterate each one
        }        
        return -1;
    }
}

but this shit is so fxxking slow

  1. Valid Anagram

very slow...

class Solution {
public boolean isAnagram(String s, String t) {
    if(s.length() != t.length()) return false;
    HashMap<Character,Integer> hm = new HashMap<>();
    for(int i = 0; i < s.length(); i++){
        char c1 = s.charAt(i), c2 = t.charAt(i);
        hm.put(c1, hm.getOrDefault(c1, 0) + 1);
        hm.put(c2, hm.getOrDefault(c2, 0) - 1);
    }
    for(int i = 0; i < s.length(); i++){
        char c = s.charAt(i);
        if(hm.get(c) != 0) return false;
    }
    return true;
    
}
}
class Solution {
    public boolean isAnagram(String s, String t) {
    if(s.length() != t.length()) return false;
    int[] table = new int[26];
    for(int i = 0; i < s.length(); i++){
        table[s.charAt(i) - 'a']++;
    }
    for(int i = 0; i < s.length(); i++){
        int cur = --table[t.charAt(i) - 'a'];
        if(cur < 0) return false;
    }
    return true;   
    }
}

a little faster than standard.

new method:

public boolean isAnagram(String s, String t) {
    if(s.length() != t.length()) return false;
    if(s.length() == 0 && t.length() == 0) return true;
    char[] ch1 = s.toCharArray();
    char[] ch2 = t.toCharArray();
    Arrays.sort(ch1);
    Arrays.sort(ch2);
    int i = 0 , j = 0, n = s.length();
    while(i < n && j < n){
        if(ch1[i] != ch2[j]) return false;
        i++;
        j++;
    }   
    return true;
}
  1. Delete Node in a Linked List

understand linkedlist

class Solution {
public void deleteNode(ListNode node) {
    node.val = node.next.val;
    node.next = node.next.next;        
}
}
  1. Valid Palindrome two pointers, magical .toLowerCase() and .toCharArray() and .isLetterOrDigit() will satisfy the requirements
class Solution {
public static boolean isPalindrome(String s) {
    s = s.toLowerCase();
    char[] chars = s.toCharArray();
    int i = 0, j = chars.length - 1;
    while(i < j){
        if(!Character.isLetterOrDigit(chars[i])){
            i++;
            continue;
        }
        if(!Character.isLetterOrDigit(chars[j])){
            j--;
            continue;
        }
        if(chars[i++] != chars[j--]) return false;
    }
    return true;
}
}
  1. Power of Three

let's take a look at three methods of this problem as follow up:

  1. for loop:

if n cant be divided by 3, false, even so, after many times, it won't, if divided with no reserved number, then it is 1, else is 0

class Solution {
public boolean isPowerOfThree(int n) {
    if(n < 1) return false; //3^0 = 1
    while(n % 3 == 0) n /= 3;
    return n == 1;
    }
}
  1. math: log function:

firstly, if 3^x == n, then x == log3(n) and x is integer next, know that loga(b) == logc(b)/logc(a) mathmetically, however, in java we should use log10(b)/log10(a) instead of log(b)/log(a) which represents loge(b)/loge(a) for performance difference.

last, if the result of log3(n) is integer, log3(n) % 1 should be 0, i did not know we could do it this way.

so if to identify whether a result x is integer, we can do: x% 1== 0 ?

class Solution {
public boolean isPowerOfThree(int n) {
    return (Math.log10(n) / Math.log10(3)) % 1 == 0;
    }
}
  1. Integer limitation:

this is more tricky but easy to understand, all powers of three can be divided by bigger powers of three, like 27 % 9 == 0. in the environment, we have 32 bit signed int and the largest power of 3 is 3^(int)(log(MAX_VALUE)/log(3)), which is 19, so determine whether largest power of 3 is divisible by n. notice in this method negative numbers can also be divisible, so we need positive check.

class Solution {
public boolean isPowerOfThree(int n) {
    return n > 0 && Math.pow(3,(int)(Math.log10(Integer.MAX_VALUE) / Math.log10(3))) % n == 0;
    }
}
  1. String to Integer (atoi) so many limitations in this problem: 1.if you see spaces, skip them 2.if you meet non-digit chars first, return 0 3.if you meet '-'/ '+' they are legal 4.count the number and trans to int, if cross 32 bit signed int boundary, return Integer.MAX_VALUE or Integer.MIN_VALUE 5.if non-digit chars after number, skip

    class Solution { public int myAtoi(String str) { if(str == null || str.length() == 0) return 0; //leetcode won't recognize str.isBlank() for some reason, damn int i = 0; for(; i < str.length(); i++){ if(str.charAt(i) != ' ') break;//skip all spaces } //check if outside the string if(i == str.length()) return 0; char ch = str.charAt(i); // in case satisfy one condition below and i++ then out of boundary int flag = 1; //1 as default, or assign in first if condition if(ch == '+'){ i++; } if(ch == '-'){ flag = -1; i++; } if(i == str.length() || !Character.isDigit(str.charAt(i))) return 0; //it must be numbers at index i int ans = 0; while(i < str.length() && Character.isDigit(str.charAt(i))){ int pop = Character.getNumericValue(str.charAt(i++)); if(ans > Integer.MAX_VALUE / 10 || (ans == Integer.MAX_VALUE / 10 && pop > 7)){ return flag > 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE; } // here's the trick: 1. check overflow 2.if the absolute of number is bigger than Integer.MAX_VALUE, it must be smaller than Integer.MIN_VALUE since the boundary is [-2^31, 2^31-1] ans = ans * 10 + pop; } return flag * ans;

    } }

  2. Implement strStr() "neelde in the hay"

use substring window

class Solution {
public int strStr(String haystack, String needle) {
    if(needle.length() == 0) return 0;
    if(haystack.length() < needle.length()) return -1;
    
    int i = 0, j = needle.length();
    while(j <= haystack.length()){
        String sub = haystack.substring(i++,j++);
        if(needle.equals(sub)) return i-1;
    }
    return -1;
}
}
  1. Count and Say

my program is 7ms which is too slow, and the main difference between mine and a great one is the way to store the answer string.

class Solution {
public static String countAndSay(int n) {
    if(n == 1) return "1";
    String last = countAndSay(n-1);
    int counter = 1;
    char val = last.charAt(0);
    StringBuilder ans = new StringBuilder();
    for(int i = 1; i < last.length(); i++){
        if(last.charAt(i) == val){
            counter++;
        }
        else{
            ans.append(counter).append(val);
            counter = 1;
            val = last.charAt(i);
        }
    }
    if(counter > 0) ans.append(counter).append(val);
    return ans.toString();
    }
}
  1. Longest Common Prefix still utilize the great tool of StringBuilder.

    class Solution { public String longestCommonPrefix(String[] strs) { if(strs.length == 0 || strs[0].length() == 0) return ""; StringBuilder s = new StringBuilder(); int i = 0; while(checker(strs,i)){ s.append(strs[0].charAt(i++)); } return s.toString(); } public boolean checker(String[] strs, int i){ for(int j = 0; j < strs.length; j++){ if(i >= strs[j].length() || (strs[j].charAt(i) != strs[0].charAt(i))) return false; } return true; } }

got time and space better than 100%

class Solution {
public static ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode first = head;
    ListNode second = head;
    while(n-- > 0){
        second = second.next;
    }
    if(second == null){
    //assume the length is m, and n can only be 
    //between 0-m-1, then second pointer out of listnode means delete target is the //first listnode
        head = head.next;
        return head;
    }
    while(second.next != null){
        //if second.next happens to be null
        //means delete target is the second one
        //if not, move both to the last element.
        first = first.next;
        second = second.next;
    }
    first.next = first.next.next;
    return head;
    
}
}
  1. Remove Nth Node From End of List

    class Solution { public static ListNode removeNthFromEnd(ListNode head, int n) { ListNode first = head; ListNode second = head; while(n-- > 0){ second = second.next; } if(second == null){ //assume the length is m, and n can only be //between 0-m-1, then second pointer out of listnode means delete target is the //first listnode head = head.next; return head; } while(second.next != null){ //if second.next happens to be null //means delete target is the second one //if not, move both to the last element. first = first.next; second = second.next; } first.next = first.next.next; return head;

    } }

  2. Reverse Linked List

  1. iterative

    class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while(curr != null){ ListNode temp = curr.next; curr.next = prev; prev = curr; curr = temp; } return prev; } }

  2. recursive

    class Solution { public ListNode reverseList(ListNode head) { if(head == null || head.next == null) return head; ListNode newhead = reverseList(head.next); head.next.next = head; head.next = null; return newhead; } }

  1. *Palindrome Linked List this one is visually harder and more complicated than other problems of linked list, so the general idea is:

1.from the start(either head or your own list works) initialize two listnode

2.one is slow and another is twice faster, check if fast.next == null or fast.next.next == null, if so, then slow one reaches the middle

3.by the position of end and i to relocate j (i is slow one j is fast one)

4.reverse j -> end listnode

5.from end and start to compare equal, then return

6.necessary for each

class Solution {
public boolean isPalindrome(ListNode head) {
    if(head == null || head.next == null) return true;
    ListNode p = new ListNode(-1);
    p.next = head;
    ListNode i = p, j = p;
    while(j.next != null && j.next.next != null){
        j = j.next.next;
        i = i.next;
    }
    //if odd length, mid is between i and i.next
    //if even, mid is i.next, then rejust j position
    j = (j.next == null) ? i.next : i.next.next;
    //then reverse use iterative way
    ListNode prev = null;
    while(j != null){
        ListNode temp = j.next;
        j.next = prev;
        prev = j;
        j = temp;
    }
    //now reversed and j should be null, prev should be new head
    //so we use j
    j = prev;
    p = p.next;
    while(p != null && j != null){
        if(p.val != j.val) return false;
        p = p.next;
        j = j.next;
    }
    return true;
}
}

new method:

class Solution {
public boolean isPalindrome(ListNode head) {
    if(head == null || head.next == null) return true;
    List<Integer> list = new ArrayList<>();
    Stack<Integer> stack = new Stack<>();
    while(head != null){
        list.add(head.val);
        stack.push(head.val);
        head = head.next;
    }
    int i = 0;
    while(!stack.isEmpty()){
        if(!stack.pop().equals(list.get(i))) return false;
        i++;
    }
    return true;
}
}
  1. Linked List Cycle
  1. hashset for self defined data type

    public class Solution { public boolean hasCycle(ListNode head) { //it seems abstract to identify a ListNode //but we can have a HashSet with ListNode type Set s = new HashSet<>(); while(head != null) { if(s.contains(head)) return true; s.add(head); head = head.next; } return false; } }

  2. two pointers //two runners with different speed running on a track, if the track is not circle //fast one will reach the end //if circle, eventually they will meet

    public class Solution { public boolean hasCycle(ListNode head) { if(head == null || head.next == null) return false; ListNode f = head.next, s = head; while(f != s){ if(f.next == null || f.next.next == null) return false; f = f.next.next; s = s.next; } return true; } }

  1. Maximum Depth of Binary Tree
class Solution {
public int maxDepth(TreeNode root) {
    if(root == null) return 0;
    if(root.right == null && root.left == null) return 1;
    //otherwise the depth is the maximum of root.left and root.right plus one for root
    return Math.max( (root.right == null) ? 0 : 1 + maxDepth(root.right), (root.left == null) ? 0 : 1 + maxDepth(root.left));
    
}
}
  1. Validate Binary Search Tree
  1. recursion with recursive method, each tree root not only: 1.root.left.val < root.val and root.right.val > root.val but also: 2.root.val satisfies the upper and lower bound

    class Solution { public boolean isValidBST(TreeNode root) { return valid(root, null, null); } public boolean valid(TreeNode root, Integer upper, Integer lower){ //notice only Integer has null type, not int if(root == null) return true; int val = root.val; if((upper != null && val >= upper) || (lower != null && val <= lower)) return false; return (valid(root.left, val, lower) && valid(root.right, upper, val)); } }

*2) in-order in-order method for BST returns a ascending sequences, where each element is smaller thant next.

class Solution {
public boolean isValidBST(TreeNode root) {
    Stack<TreeNode> s = new Stack();
    double lastval = - Double.MAX_VALUE;
    //with some extreme case, and the range of double, this is the only feasible way
    
    while(!s.isEmpty() || root != null){
        while(root != null){
            s.push(root);
            root = root.left;
        }
        root = s.pop();
        if(root.val <= lastval) return false;
        lastval = root.val;
        root = root.right;
    }
    return true;
    
}
}
  1. Symmetric Tree
  1. recursive

    class Solution { public boolean isSymmetric(TreeNode root) { if(root == null) return true; return isMirror(root.left, root.right); } public boolean isMirror(TreeNode l, TreeNode r){ if(l == null && r == null) return true; if(l == null || r == null) return false; return (l.val == r.val) && isMirror(l.left, r.right) && isMirror(l.right, r.left); } }

  2. iterative

    class Solution { public boolean isSymmetric(TreeNode root) { if(root == null) return true; Queue q = new LinkedList<>(); q.add(root.left); q.add(root.right); while(!q.isEmpty()){ TreeNode l = q.poll(); TreeNode r = q.poll(); if(l == null && r == null) continue; if(l == null || r == null || l.val != r.val) return false; q.add(l.left); q.add(r.right); q.add(l.right); q.add(r.left); } return true; } }

  1. Binary Tree Level Order Traversal to understand the data structure is the key: the goal is to iterate each node and store in a list of a list, each sub-list in the list represents a level of the tree, and the vals in the sub-list are the nodes of this level.

notice that the length of the list is the number of levels, the length of sub-list is the nodes in this level

class Solution {
public List<List<Integer>> tree = new ArrayList<List<Integer>>();
public void traversal(TreeNode node, int level){
    if(tree.size() == level) tree.add(new ArrayList<Integer>());
    //level starts from 0, if tree has same length as level, means
    //one more level of nodes needed
    tree.get(level).add(node.val);
    //tree.get() has a type of List, and add current value
    if(node.left != null) traversal(node.left, level + 1);
    if(node.right != null) traversal(node.right, level + 1);
}
public List<List<Integer>> levelOrder(TreeNode root) {
    if(root == null) return tree;
    traversal(root, 0);
    return tree;
}
}
  1. Convert Sorted Array to Binary Search Tree
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
    return sortedArrayToBST(nums, 0, nums.length);
}
private TreeNode sortedArrayToBST(int[] nums, int start, int end){
    if(start == end) return null;
    int mid = start + (end - start) / 2;
    TreeNode root = new TreeNode(nums[mid]);
    root.left = sortedArrayToBST(nums, start, mid);
    root.right = sortedArrayToBST(nums, mid + 1, end);
    return root;
}
}
  1. Merge Sorted Array both beat 100% lol, this is a weird one since the structure of nums1.

    class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int[] nums = Arrays.copyOfRange(nums1, 0, m + 1); //notice this function copies from 0 - m, so m+1 needed int i = 0, j = 0, k = 0; while(i < m || j < n){ int n1 = (i == m) ? Integer.MAX_VALUE : nums[i]; int n2 = (j == n) ? Integer.MAX_VALUE : nums2[j]; if(n1 <= n2) nums1[k++] = nums[i++]; if(n1 > n2) nums1[k++] = nums2[j++]; } } }

  2. First Bad Version notice that in binary search, mid = (start + end) / 2 could overflow, a better way: mid = start + (end - start) / 2

public class Solution extends VersionControl {
public int firstBadVersion(int n) {
    int hi = n, lo = 1;
    while(lo <= hi){
        int mid = lo + (hi - lo) / 2;
        if(isBadVersion(mid)) hi = mid - 1;
        else lo = mid + 1;
    }
    return lo;
}
}
  1. *Climbing Stairs not quite understand dynamic programming, just to get a quick review and code.

    class Solution { public int climbStairs(int n) { if(n == 1) return 1; int[] dp = new int[n + 1]; dp[1] = 1; dp[2] = 2; for(int i = 3; i < n + 1; i++){ dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n]; } }

  2. Best Time to Buy and Sell Stock there's only two cases for each prices in the array:

  3. higher than the lowest price recorded

  4. lower than it

for the first case, we calculate the profit from lowest price recorded to this price, if it generates more profit than the max profit recorded, replace it

for the second case, this mean lower prices occurs, but the profit could still be the same

class Solution {
public int maxProfit(int[] prices) {
    int profit = 0;
    int lowestPrice = Integer.MAX_VALUE;
    for(int i = 0; i < prices.length; i++){
        if(prices[i] < lowestPrice) lowestPrice = prices[i];
        else if(profit < prices[i] - lowestPrice) profit = prices[i] - lowestPrice;
    }
    return profit;
}
}
  1. Maximum Subarray
  1. brute force

    class Solution { public int maxSubArray(int[] nums) { int sum = 0; int ans = Integer.MIN_VALUE; for(int i = 0; i < nums.length; i++){ for(int j = 0; j <= i; j++){ sum = sumOfSub(nums, j, i); ans = Math.max(sum, ans); } } return ans; } private int sumOfSub(int[] nums, int start, int end){ int sum = 0; for(int i = start; i <= end; i++){ sum += nums[i]; } return sum; } }

  2. dynamic programming

    class Solution { public int maxSubArray(int[] nums) { if(nums.length == 0) return 0; int ans = nums[0]; int sumBeforeCur = nums[0]; for(int i = 1; i < nums.length; i++){ sumBeforeCur = Math.max(sumBeforeCur + nums[i], nums[i]); ans = Math.max(ans, sumBeforeCur); } return ans; } }

  1. House Robber 1)optimal structure for each state 2)state transfer equation
class Solution {
public int rob(int[] nums) {
    int n = nums.length;
    if(n == 0) return 0;
    if(n == 1) return nums[0];
    if(n == 2) return Math.max(nums[0], nums[1]);
    int first = nums[0];
    int second = nums[1];
    for(int i = 3; i <= n; i++){
        int max = Math.max(first + nums[i - 1], second);
        first = second;
        second = max;
    }
    return second;
    
}
}
  1. Missing Number 1)my way: 1ms
class Solution {
public int missingNumber(int[] nums) {
    
    int maxNum = Integer.MIN_VALUE;
    int realSum = 0;
    int expectSum = 0;
    for(int num:nums){
        maxNum = Math.max(maxNum, num);
        realSum += num;
    }
    for(int i = 0; i <= maxNum; i++) expectSum += i;
    if(nums.length == maxNum) return expectSum - realSum;
    else return maxNum + 1;
}
}

2)sorting: even worse... 7ms

class Solution {
public int missingNumber(int[] nums) {
    Arrays.sort(nums);
    if(nums[nums.length-1] != nums.length) return nums.length;
    else if(nums[0] != 0) return 0;
    
    for(int i = 0; i < nums.length; i++){
        if(nums[i] != i) return i;
    }
    return -1;
    
   
}
}

3)hashset: even worse ??? 9ms

class Solution {
public int missingNumber(int[] nums) {
    Set<Integer> set = new HashSet<>();
    for(int num:nums) set.add(num);
    for(int i = 0; i < nums.length + 1; i++){
        if(!set.contains(i)) return i;
    }
    return -1;
   
}
}

4)gauss formula: with this hint, i realize my method 1) can be improved: 0ms

class Solution {
public int missingNumber(int[] nums) {
    int n = nums.length;
    int expSum = (n + 1) * n / 2;
    int actSum = 0;
    for(int num:nums) actSum += num;
    return expSum - actSum;
}
}

so the difference (main diff is the if statement in the end of method 1)) is because in my method, i use sum of 0 - num.length (also is maxValue seen) as expected sum, but in fact, for a n-length array, the expected sum is sum of 0 - (n + 1) (e.g. when given [0], the exp sum is 1)

public class Solution {
private int[] oriarray;
private int[] numsarray;

public Solution(int[] nums){
    this.oriarray = Arrays.copyOf(nums,nums.length);
    this.numsarray = nums;
}

public int[] reset(){
    return oriarray;
}

public int[] shuffle(){
    Random randomgen = new Random();
    for(int i = 0; i < numsarray.length; i++){
        int temp = numsarray[i];
        int randomIndex = randomgen.nextInt(numsarray.length);
        numsarray[i] = numsarray[randomIndex];
        numsarray[randomIndex] = temp;
    }
    return numsarray;
}
}
  1. Min Stack
class MinStack {
/** initialize your data structure here. */
Stack<Integer> s;
int min;
public MinStack() {
    s = new Stack<>();
    min = Integer.MAX_VALUE;
}

public void push(int x) {
   if(x <= min){//this must be leq,if it only is <
   // when x == min pushed into stack, when pop there will be two numbers
   // popped since min is the same as the x
    s.push(min);
    min = x;
   }
   s.push(x);
}

public void pop() {
    if(min == s.pop()) min = s.pop();
}

public int top() {
    return s.peek();
}

public int getMin() {
    return min;
}
}
  1. Count Primes
  1. not optimal:

    class Solution { public int countPrimes(int n) { boolean[] isPrimes = new boolean[n+1]; Arrays.fill(isPrimes, true);

     for(int i = 2; i < n; i++){
         if(isPrimes[i]){
             for(int j = i * 2; j < n; j += i){
                 isPrimes[j] = false;
             }
         }
     }
     int count = 0;
     for(int i = 2; i < n; i++){
         if(isPrimes[i]) count++;
     }
     return count;
    

    } }

  2. with improvement [Sieve of Eratosthenes]

    class Solution{ public int countPrimes(int n){ boolean[] isPrime = new boolean[n]; Arrays.fill(isPrime, true); for(int i = 2; i < Math.sqrt(n); i++){ if(isPrime[i]){ for(int j = i * i; j < n; j += i) isPrime[j] = false; } } int ans = 0; for(int i = 2; i < n; i++) ans = isPrime[i] ? ans + 1 : ans; return ans; } }

  1. Roman to Integer

    class Solution { public static int romanToInt(String s) { if(s == null || s.length() == 0) return 0; Map<Character, Integer> hm = new HashMap<>(); hm.put('I', 1); hm.put('V', 5); hm.put('X', 10); hm.put('L', 50); hm.put('C', 100); hm.put('D', 500); hm.put('M', 1000); // int sum = 0, n = s.length(); for(int i = 0; i < n; i++){ int value = hm.get(s.charAt(i)); if(i != n - 1 && value < hm.get(s.charAt(i + 1))) sum -= value; else sum += value; } return sum; } }

  2. Number of 1 Bits

another method uses no less memory, i dont wanna spend time on it.

public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
    int ans = 0;
    int mask = 1; //00000...0001b
    for(int i = 0; i < 32; i++){
        if((n & mask) != 0) ans++;//& bit operation, && boolean operation
        mask <<= 1;//left shift 1 bit
    }
    return ans;
}
}
  1. Hamming Distance
class Solution {
public int hammingDistance(int x, int y) {
    int ans = (x ^ y);
    int mask = 1, counter = 0;
    for(int i = 0; i < 32; i++){
        if((mask & ans) != 0) counter++;
        //notice (mask & ans) == 1 is wrong
        //since the result of "and" operation is 32 bit
        //and its not gonna be 1
        mask <<= 1;
    }
    return counter;
}
}
  1. Reverse Bits use bit operation to solve bit problems
public class Solution {
// you need treat n as an unsigned value
public static int reverseBits(int n) {
    int ans = 0;//use 0 to have 32 bit 0s
    for(int i = 0; i < 32; i++){
        int cur = (n >> i);//cur to be i-th digit
        cur &= 1;//filter all other digits
        cur <<= (31 - i);//left shift 31 - i to reverse
        ans |= cur;// store the result;
    }
    return ans;
}
}
  1. Pascal's Triangle
class Solution {
 public static List<List<Integer>> generate(int numRows){
    List<List<Integer>> ans = new ArrayList<>();
    if(numRows == 0) return ans;
    List<Integer> first = new ArrayList<>();
    first.add(1);
    ans.add(first);
    if(numRows == 1) return ans;
    for(int i = 1; i < numRows; i++){
        List<Integer> curRow = new ArrayList<>();
        for(int j = 0; j < i + 1; j++){
            if(j == 0 || j == i) curRow.add(1);
            else curRow.add(ans.get(i - 1).get(j - 1) + ans.get(i - 1).get(j));
        }
        ans.add(curRow);
    }
    return ans;

}
}

############# so far this section is finished, then I am gonna review on those problems, it's gonna be in a new article #############