Leetcode 24. Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head.

For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

Analysis:

Have a dummy node and a temporal node. Iterate the whole list and change every node pair.

Nice to have the figure to help understand.

swap-node

Time complexity: O(n)

Space complexity: O(1)

Code is below:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode swapPairs(ListNode head) {
        // O(n)
        
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode dummy = new ListNode(0);
        ListNode node = dummy;
        dummy.next = head;
        
        while (head != null && head.next != null) {
            // First operation
            node.next = head.next;
            head.next = node.next.next;
            node.next.next = head;
            
            // Go to another round
            node = head;
            head = head.next;
        }
        
        return dummy.next;
    }
}

Leetcode 92 & 206. Reverse Linked List I & II

Reverse a singly linked list.

click to show more hints.

Hint:A linked list can be reversed either iteratively or recursively. Could you implement both?

Analysis:

For iteration, we need to have a prev and next node for temporal save.

For recursive,

Assume that the rest of the list had already been reversed, now how do I reverse the front part? Let’s assume the list is: n1 → … → nk-1 → nk → nk+1 → … → nm → Ø

Assume from node nk+1 to nm had been reversed and you are at node nk.

n1 → … → nk-1nk → nk+1 ← … ← nm

We want nk+1’s next node to point to nk.

So, nk.next.next = nk

Time complexity: O(n)

Space complexity: O(1)

Code is below:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseList(ListNode head) {
        // O(n)
        
        if (head == null || head.next == null) {
            return null;
        }
        
        // iteration
        ListNode current = head;
        ListNode prev = null;
        ListNode next;
        
        while (current != null) {
            next = current.next;
            current.next = prev;
            prev = current;
            current = next;
        }
        
        return prev;
        
        // recursive
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        
        return p;
    }
}

Followup:
Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.

Analysis:
Go through the list and find the position before m. Then start from m, reverse the n-m nodes like reverse linked list.

Time complexity: O(n)
Space complexity: O(1)

Code is below:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        // O(n)
        
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode dummy = new ListNode(0);
        ListNode prev = dummy;
        dummy.next = head;
        
        // Find the position before the reverse start
        for (int i = 0; i < m - 1; i++) {
            prev = prev.next;
        }
        
        // Reverse the n - m nodes
        ListNode cur = prev.next;
        for (int i = 0; i < n - m; i++) {
            ListNode next = cur.next;
            cur.next = next.next;
            next.next = prev.next;
            prev.next = next;
        }
        
        return dummy.next;
    }
}

Leetcode 121. Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Example 1:

Input: [7, 1, 5, 3, 6, 4]
Output: 5

max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)

Example 2:

Input: [7, 6, 4, 3, 1]
Output: 0

In this case, no transaction is done, i.e. max profit = 0.

Analysis:
Go through the whole array and maintains the min value and the max profit.

Time complexity: O(n)
Space complexity: O(1)

Code is below:

public class Solution {
    public int maxProfit(int[] prices) {
        // O(n) 
        
        if (prices == null || prices.length == 0) {
            return 0;
        }
        
        // The smallest value and the profit
        int min = Integer.MAX_VALUE;
        int profit = 0;
        
        for (int price : prices) {
            // update the min value and the max profit
            min = price < min ? price : min;             profit = (price - min) > profit ? price - min : profit;
        }
        
        return profit;
    }
}

Leetcode 168 & 171. Excel Sheet Column Title / Number

Given a positive integer, return its corresponding column title as appear in an Excel sheet.

For example:

    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB

Analysis:
当n > 0时, 假如n % 26 == 0,则n为26的倍数,要转换为’Z’插入队首,之后n = n / 26 – 1, 假如n % 26 != 0, 则使用一般方法计算字符,int c = ‘A’ + n % 26 – 1, 之后 n /= 26。

Time complexity: O(n)
Space complexity: O(1)

Code is below:

public class Solution {
    public String convertToTitle(int n) {
        // O(n)
        
        if (n <= 0) {             return "";         }                  StringBuilder sb = new StringBuilder();                  while (n > 0) {
            if (n % 26 == 0) {
                sb.insert(0, 'Z');
                n = n / 26 - 1;
            } else {
                int c = 'A' + n % 26 - 1;
                sb.insert(0, (char) c);
                n /= 26;
            }
        }
        
        return sb.toString();
    }
}

Followup:
Related to question Excel Sheet Column Title

Given a column title as appear in an Excel sheet, return its corresponding column number.

For example:

A -> 1
B -> 2
C -> 3

Z -> 26
AA -> 27
AB -> 28

Analysis:
得到数字,其实就是把26进制的数转换为10进制的数。算法就是基本的进制转换方法,从后往前第n位的值乘上26^(n-1)。这里26进制数是1开始的,即A是1

Time complexity: O(n)
Space complexity: O(1)

Code is below:

public class Solution {
    public int titleToNumber(String s) {
        // O(n)
        
        int res = 0;
        
        for (int i = 0; i < s.length(); i++) {
            res = res * 26 + (s.charAt(i) - 'A' + 1);
        }
        
        return res;
    }
}

Leetcode 151 & 186. Reverse Words in a String I& II

Given an input string, reverse the string word by word.

For example,
Given s = “the sky is blue“,
return “blue is sky the“.

Analysis:

Use extra place. To split the whole string and get a string array, then go from the back and put them in a new string.

Time complexity : O(n)

Space complexity: O(n)

Code is below:

public class Solution {
    public String reverseWords(String s) {
        // O(n) O(n)
        
        if (s == null || s.length() == 0) {
            return "";
        }
        
        s = s.trim();
        String[] str = s.split(" ");
        StringBuilder sb = new StringBuilder();
        
        for (int i = str.length - 1; i >= 0; i--) {
            if (!str[i].equals("")) {
                sb.append(str[i]).append(" ");
            }
        }
        
        return sb.toString().trim();
    }
}

Followup:
Could you do it in-place without allocating extra space?

Analysis:
Use str.toCharArray() to change it to char array. Then reverse the whole array. Scan the array, if find a ‘ ‘, then reverse it from beginning. Update the start.

Time complexity : O(n)

Space complexity: O(1)

Code is below:

public class Solution {
    public void reverseWords(char[] s) {
        // O(n) O(1)
        
        if (s == null || s.length == 0) {
            return;
        }
        
        // reverse the whole array
        reverse(s, 0, s.length - 1);
        
        //reverse part of the words
        for (int i = 0, start = 0; i <= s.length; i++) {
            if (i == s.length || s[i] == ' ') {
                reverse(s, start, i - 1);
                start = i + 1;
            }
        }
    }
    
    public void reverse(char[] s, int start, int end) {
        while (start < end) {
            char c = s[start];
            s[start] = s[end];
            s[end] = c;
            start++;
            end--;
        }
    }
}

Leetcode 8. String to Integer (atoi)

Implement atoi to convert a string to an integer.

Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.

Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

 

Requirements for atoi:The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

Analysis:

Lots of corner case to be considered:

  • number start or end with black space – use str.trim()
  • number start with + / – – with a sign
  • number out of range Integer range [-2147483648, 2147483647]

Note: to get the integer value of a string number, like ‘1’, we can use the char – ‘0’

For integer out of range, we need to check the res with the Integer.MAX_VALUE. If the last value is larger than 8 and the res = MAX /10, then it’s overflow.

To check a char is digit, we can use Character.isDigit(char).

Time complexity: O(n)

Space complexity: O(1)

Code is below:

public class Solution {
    public int myAtoi(String str) {
        // O(n) O(1)
        
        if (str == null || str.length() == 0) {
            return 0;
        }
        
        // To get rid of the leading and tailing blank space like " -1234 "
        str = str.trim();
        
        // Set the sign
        int sign = 1;
        
        int i = 0;
        
        // Check of "+" and "-"
        if (str.charAt(0) == '+') {
            i++;
        }
        
        if (str.charAt(0) == '-') {
            sign = -1;
            i++;
        }
        
        int res = 0;
        
        while (i < str.length() && Character.isDigit(str.charAt(i))) {             // Get the current digit             int digit = (int) (str.charAt(i) - '0');                          // Integer range [-2147483648, 2147483647]             if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && digit >= 8)) {
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            
            res = res * 10 + digit;
            i++;
        }
        
        return sign * res;
   
        //return Integer.valueOf(str);
    }
}

Leetcode 54 & 59. Spiral Matrix I & II

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example,
Given the following matrix:

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

You should return [1,2,3,6,9,8,7,4,5].

Analysis:

Try to follow the steps from left to right, to bottom to left to up.

Note to consider the situations where row/col = 1

Time complexity: O(mn)

Space complexity: O(1)

The code is below:

public class Solution {
    public List spiralOrder(int[][] matrix) {
        // O(mn)
        List result = new ArrayList<>();
        
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return result;
        }
        
        int row = matrix.length;
        int col = matrix[0].length;
        int x = 0;
        int y = 0;
        
        while (row > 0 && col > 0) {
            // Only one row
            if (row == 1) {
                for (int i = 0; i < col; i++) {
                    result.add(matrix[x][y++]);
                }
                break;
            }
            
            // Only one col
            if (col == 1) {
                for (int i = 0; i < row; i++) {
                    result.add(matrix[x++][y]);
                }
                break;
            }
            
            // Move from top to right
            for (int i = 0; i < col - 1; i++) {
                result.add(matrix[x][y++]);
            }
            
            // Move from right to bottom
            for (int i = 0; i < row - 1; i++) {
                result.add(matrix[x++][y]);
            }
            
            // Move from bottem to lef
            for (int i = 0; i < col - 1; i++) {
                result.add(matrix[x][y--]);
            }
            
            // Move from left to top
            for (int i = 0; i < row - 1; i++) {
                result.add(matrix[x--][y]);
            }
            
            row -= 2;
            col -= 2;
            x++;
            y++;
        }
        return result;
    }
}

Followup:
Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

For example,
Given n = 3,

You should return the following matrix:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]

Analysis:
Similar to the first question.

Time complexity: O(mn)

Space complexity: O(1)

Code is below:

public class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        
        int num = 1;
        int x = 0;
        int y = 0;
        int row = n;
        int col = n;
        
        while (num <= n * n) {
            // one row/col
            if (row == 1 || col == 1) {
                matrix[x][y] = num;
                break;
            }
            
            // top to right
            for (int i = 0; i < col - 1; i++, num++) {
                matrix[x][y++] = num;
            }
            
            // right to bottom
            for (int i = 0; i < row - 1; i++, num++) {
                matrix[x++][y] = num;
            }
            
            // bottom to left
            for (int i = 0; i < col - 1; i++, num++) {
                matrix[x][y--] = num;
            }
            
            // left to top
            for (int i = 0; i < row - 1; i++, num++) {
                matrix[x--][y] = num;
            }
            
            row -= 2;
            col -= 2;
            x++;
            y++;
        }
        
        return matrix;
    }
}

Leetcode 1, 167 & 170 Two Sum I, II && III

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Analysis:

To get two values which the sum of them equals to the target, the brute force one is to have 2 for loop to go over the array twice. This could take O(n^2).

So consider how to get an value very quick, we can have hashtable, which can quickly get the value in nearly O(1).

So basically, what we can do it to put all values in a hash table. Then go over it again to find another value.

Note: here we use the value as key and the index as the value.

Time complexity: O(n)

Space complexity: O(n)

The code is below:

public class Solution {
    public int[] twoSum(int[] nums, int target) {
        // Hashtable O(n) O(n)
        
        // Corner case
        if (nums == null || nums.length == 0) {
            return null;
        }
        
        HashMap<Integer, Integer> map = new HashMap<>();
        
        // number as key, index as value
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], i);
        }
        
        for (int i = 0; i < nums.length; i++) {
            int temp = target - nums[i];
            if (map.containsKey(temp) && map.get(temp) != i) {
                return new int[] {i, map.get(temp)};
            }
        }
        
        return null;
    }
}

 

Follow up:

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

Analysis:

Sorted array? Very familiar? Yes, binary search.

Also we can use another powerful method called two pointers: we can have a start and end. If start + end = target, then return them. If start + end < target, we know that start is small, so we add start by 1. Otherwise reduce the end by 1.

Time complexity: O(n)

Space complexity: O(1)

The code is below:

public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        //Two pointers O(n) O(1)
        
        // Corner case
        if (numbers == null || numbers.length == 0) {
            return null;
        }
        
        int start = 0;
        int end = numbers.length - 1;
        
        while (start < end) {
            if (numbers[start] + numbers[end] == target) {
                return new int[] {start + 1, end + 1};
            } else if (numbers[start] + numbers[end] < target) {
                start++;
            } else {
                end--;
            }
        }
        return null;
    }
}

Followup:
Design and implement a TwoSum class. It should support the following operations: add and find.

add – Add the number to an internal data structure.
find – Find if there exists any pair of numbers which sum is equal to the value.

For example,
add(1); add(3); add(5);
find(4) -> true
find(7) -> false

Analysis:

This is more like a design problem. So we can use the similar method to have a hash table to store the value. For adding, we can use map.put() and for finding, we can go through the entrySet and find another value.

Note: for special case where we have multiple values to be the same, like 0, 0, 0 if we want to find 0, it also should return true. So we should add a condition that, if i == j then the occurrence should be larger than 1.

Time complexity: O(n)

Space complexity: O(n)

The code is below:

public class TwoSum {

    HashMap<Integer, Integer> map = new HashMap<>();

    // Add the number to an internal data structure.
	public void add(int number) {
	    if (map.containsKey(number)) {
	        map.put(number, map.get(number) + 1);
	    } else {
	        map.put(number, 1);
	    }
	}

    // Find if there exists any pair of numbers which sum is equal to the value.
    public boolean find(int value) {
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            // Find i + j == value
            int i = entry.getKey();
            int j = value - i;
            
            // special case when i == j 
            if ((i == j && entry.getValue() > 1) || (i != j && map.containsKey(j))) {
                return true;
            }
        }
        return false;
    }
	
}


// Your TwoSum object will be instantiated and called as such:
// TwoSum twoSum = new TwoSum();
// twoSum.add(number);
// twoSum.find(value);

Leetcode 33 & 81. Search in Rotated Sorted Array I & II

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Analysis:

For rotated array, we must have figure to analysis it. Basically it falls into the following two cases: either the mid is larger than the end, or the mid is smaller than the end.

Then in each case, we can use binary search to find the target value. Note that, we should compare both the start, mid, end with the target.

img_4163

Time complexity: O(logn)

Space complexity: O(1)

Below is the code:

public class Solution {
    public int search(int[] nums, int target) {
        // O(logn) binary search
        
        // Corner case
        if (nums == null || nums.length == 0) {
            return -1;
        }
        
        int start = 0;
        int end = nums.length - 1;
        
        while (start + 1 < end) {             int mid = start + (end - start) / 2;             if (nums[mid] == target) {                 return mid;             }             // case 1             if (nums[mid] > nums[end]) {
                if (nums[mid] >= target && target >= nums[start]) {
                    end = mid;
                } else {
                    start = mid;
                }
            } else { // case 2
                if (nums[mid] <= target && target <= nums[end]) {
                    start = mid;
                } else {
                    end = mid;
                }
            }
        }
        
        if (nums[start] == target) {
            return start;
        } else if (nums[end] == target) {
            return end;
        }
        
        return -1;
    }
}

Follow up:
Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.

Analysis:
In this case, if duplicates allowed, then we can not use binary search. So normally just use the brute force method.

The code is below:

public class Solution {
    public boolean search(int[] nums, int target) {
        // O(n) normally won't apprear during interview
        
        if(nums == null || nums.length == 0) {
            return false;
        }
        
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target) {
                return true;
            }
        }
        
        return false;
    }
}

Leetcode 33. Search in Rotated Sorted Array

Leetcode 33. Search in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Analysis:

This is a common problem for Binary search. Here the array is not normally sorted, but rotated. But we can still use the Binary search to reduce the search range to half.

However, we need to add more conditions to check the range, we need to draw two lines here to help us understand the rotated sorted array.

Time complexity: O(logn)

Space complexity: O(1)

public class Solution {
    public int search(int[] nums, int target) {
        // Binary search O(logn)
        
        // Corner Case
        if (nums == null || nums.length == 0) {
            return -1;
        }
        
        int start = 0;
        int end = nums.length - 1;
        
        while (start + 1 < end) {
            int mid = start + (end - start) / 2;
            
            if (nums[mid] == target) {
                return mid;
            } 
            
            // One line
            if (nums[start] < nums[mid]) {
                if (nums[start] <= target && nums[mid] >= target) {
                    end = mid;
                } else {
                    start = mid;
                }
            } else { 
                // Another line
                if (nums[mid] <= target && nums[end] >= target) {
                    start = mid;
                } else {
                    end = mid;
                }
            }
        }
        
        if (nums[start] == target) {
            return start;
        }
        
        if (nums[end] == target) {
            return end;
        }
        
        return -1;
    }
}

 

Extention: 81. Search in Rotated Sorted Array II

Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.

If we have duplicates in the array, could we use the binary search?

No!

Because we cannot cut the array to half, as the other half may contain the same number as previous half.