Leetcode-Insertion Sort List(Java)

Question:

Sort a linked list using insertion sort.

Thinking:

As the question state, we should apply the insertion sort method to linked list. So we create a ListNode for hold the sorted list, and scan the unsorted list and pick up element to compare the element in the sorted list. Then determine when to insert the value.

Solution:

public class Solution {
    public ListNode insertionSortList(ListNode head) {
        if (head == null || head.next == null)
            return head;
        ListNode res = new ListNode(-1);
        res.next = head;
        ListNode p = res;
        ListNode next = head.next;
        head.next = null;
        head = next;
        while (head != null){
            while (p.next != null){
                //if the value is smaller than one of the sorted list, insert behind it
                if (head.val < p.next.val){
                    next = head.next;
                    head.next = p.next;
                    p.next = head;
                    head = next;
                    p = res;
                    break;
                }
                p = p.next;
            }
            //if the value is bigger than anyone of the sorted list, insert after the whole list
            if (p.next == null){
                next = head.next;
                p.next = head;
                head.next = null;
                head = next;
                p = res;
            }
        }

        return res.next;
    }
}

I also copy a refining version of this algorithm from reference: http://www.cnblogs.com/springfor/p/3862468.html

public ListNode insertionSortList(ListNode head) {  
    if(head == null||head.next == null)  
        return head;  
    ListNode sortedlisthead = new ListNode(0);  
    ListNode cur = head;
    while(cur!=null){  
        ListNode next = cur.next;  
        ListNode pre = sortedlisthead;  
        while(pre.next!=null && pre.next.val<cur.val)  
            pre = pre.next;  
        cur.next = pre.next;  
        pre.next = cur;  
        cur = next;  
    }  
    return sortedlisthead.next;  
}

Sort Algorithms

Survey:

This time, we talk about eight kinds of sort algorithms: insertion sort, shell’s sort, simple selection sort, heap sort, bubble sort, quick sort, merge sort and radix sort.

Insertion sort:

Main Idea:

From the beginning of the list, get one value at a time and insert the value into right position of sorted list until all the values are sorted. And insertion sort is stalbe.

Process: (From Wikimedia)

Pseudocode:

for i ← 1 to length(A) - 1
    j ← i
    while j > 0 and A[j-1] > A[j]
        swap A[j] and A[j-1]
        j ← j - 1
    end while
end for

Implemention in Java:

public static void InsertionSort(int[] num)
{
     int j;
     int key;
     int i;  

     for (j = 1; j < num.length; j++){
        key = num[j];
        for(i = j - 1; (i >= 0) && (num[i] < key); i--){
            num[i+1] = num[i];
        }
        num[i+1] = key;
    }
}

Complexity:

Runtime: O(n^2)

Memery: O(1)


ShellSort:

Main Idea:

The method starts by sorting pairs of elements far apart from each other, then progressively reducing the gap between elements to be compared. Starting with far apart elements can move some out-of-place elements into position faster than a simple nearest neighbor exchange.

Process:(From Wikimedia)

Pesedocode:

gaps = [701, 301, 132, 57, 23, 10, 4, 1]

foreach (gap in gaps)
{
    # Do a gapped insertion sort for this gap size.
    # The first gap elements a[0..gap-1] are already in gapped order
    # keep adding one more element until the entire array is gap sorted
    for (i = gap; i < n; i += 1)
    {
        # add a[i] to the elements that have been gap sorted
        # save a[i] in temp and make a hole at position i
        temp = a[i]
        # shift earlier gap-sorted elements up until the correct location for a[i] is found
        for (j = i; j >= gap and a[j - gap] > temp; j -= gap)
        {
            a[j] = a[j - gap]
        }
        # put temp (the original a[i]) in its correct location
        a[j] = temp
        }
    }

Implemention in Java:

public void shellSort() {
    int inner, outer;
    long temp;
    //find initial value of h
    int h = 1;
    while (h <= len / 3)
      h = h * 3 + 1; // (1, 4, 13, 40, 121, ...)

    while (h > 0) // decreasing h, until h=1
    {
      // h-sort the file
      for (outer = h; outer < len; outer++) {
        temp = data[outer];
        inner = outer;
        // one subpass (eg 0, 4, 8)
        while (inner > h - 1 && data[inner - h] >= temp) {
          data[inner] = data[inner - h];
          inner -= h;
        }
        data[inner] = temp;
      }
      h = (h - 1) / 3; // decrease h
    }
}

Simple Selection Sort

Main Idea:

Find the smallest(biggest) element in array, put it in the first place. Then find the second smallest… Do these until all the element are sorted.(I suppose it’s a little similar with bubble sort)

Process:(From Wikimedia)

Pesedocode:

for i ← 1 to length(A) - 1
    j ← i
    while j > 0 and A[j-1] > A[j]
        swap A[j] and A[j-1]
        j ← j - 1
    end while
end for

Complexity:

Runtime: O(n^2)
Memery: O(1)

Heapsort

Main Idea:

Use data structure heap which will store the smallest or biggest value of the array. Then pick up the root of heap once a time to sort.

Heapsort is a comparison-based sorting algorithm. Heapsort can be thought of as an improved selection sort: like that algorithm, it divides its input into a sorted and an unsorted region, and it iteratively shrinks the unsorted region by extracting the largest element and moving that to the sorted region. The improvement consists of the use of a heap data structure rather than a linear-time search to find the maximum.

This sort is the most important part in this article. I’ll talk about the relative operation and its performance and all the code.

Process:(From Wikimedia)

In the heap view(an example offered):

Data Structure:

Heap:

A heap is built out of the data. The heap is often placed in an array with the layout of a complete binary tree. The complete binary tree maps the binary tree structure into the array indices; each array index represents a node; the index of the node’s parent, left child branch, or right child branch are simple expressions. For a zero-based array, the root node is stored at index 0; if i is the index of the current node, then

iParent(i)     = floor((i-1) / 2)
iLeftChild(i)  = 2*i + 1
iRightChild(i) = 2*i + 2

Leetcode-Search for a Range(Java)

Question:

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

Thinking:

It’s question which should use binary search because it give us a sorted array and it requires O(log n) runtime complexity. Only thing difference between this algorithm and classical binary search is that we should make the range smaller while finding the target instead of returning the index.

Solution:

public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int low = 0;
        int high = nums.length - 1;
        int mid;
        int resl = -1;
        int resr = -1;
        while (low <= high){
            mid = (low + high) / 2;
            if (nums[mid] == target){
                if (nums[low] == target){
                    resl = low;
                    if (resr != -1)
                        break;
                }    
                else
                    low++;

                if (nums[high] == target){
                    resr = high;
                    if (resl != -1)
                        break;
                }
                else
                    high--;
            }
            else if(nums[mid] > target)
                high = mid - 1;
            else
                low = mid + 1;
        }
        int[] res = {resl, resr};
        return res;
    }

}

But the algorithm is not so effienct when finding the target so early. In order to make sure the runtime complexity is O(log n), we should also use binary search to find the lower bound and upper bound when finding the target in the array.
Reference: http://www.cnblogs.com/springfor/p/3857704.html

Code:

public int[] searchRange(int[] A, int target) {
    int [] res = {-1,-1};
    if(A == null || A.length == 0)
        return res;

    //first iteration, find target wherever it is
    int low = 0;
    int high = A.length-1;
    int pos = 0;
    while(low <= high){
        int mid = (low + high)/2;
        pos = mid;
        if(A[mid] > target)
            high = mid - 1;
        else if(A[mid] < target)
            low = mid + 1;
        else{
            res[0] = pos;
            res[1] = pos;
            break;
        }
    }

    if(A[pos] != target)
        return res;

    //second iteration, find the right boundary of this target
    int newlow = pos;
    int newhigh = A.length-1;
    while(newlow <= newhigh){
        int newmid = (newlow+newhigh)/2;
        if(A[newmid] == target)
            newlow = newmid + 1;
        else
            newhigh = newmid - 1;
    }
    res[1] = newhigh;

    //third iteration, find the left boundary of this target
    newlow = 0;
    newhigh = pos;
    while(newlow <= newhigh){
        int newmid = (newlow+newhigh)/2;
        if(A[newmid] == target)
            newhigh = newmid - 1;
        else
            newlow = newmid + 1;
    }
    res[0] = newlow;

    return res;
}

Leetcode-Partition List(Java)

Question:

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.

You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.

Thinking:

We should preserve the original relative order of the nodes. So we need two points, one is for recording where to insert the less value node, and the other is for searching the less value node.

Solution1:

public class Solution {
    public ListNode partition(ListNode head, int x) {
        if (head == null)
            return null;
        ListNode prehead = new ListNode(0);
        prehead.next = head;
        ListNode s = prehead;
        ListNode l = prehead;
        while(s != null && l != null){
            while(s.next != null){
                if (s.next.val >= x)
                    break;
                s = s.next;
            }
            l = s.next;
            if (l == null)
                break;
            while(l.next != null){
                if (l.next.val < x)
                    break;
                l = l.next;
            }
            if (l.next == null)
                break;
            ListNode tmp = l.next;
            l.next = l.next.next;
            tmp.next = s.next;
            s.next = tmp;
        }

        return prehead.next;
    }

}

And there is another solution, which uses two lists. One is for recording less value node, and the other is for recording greater value node. And connect them:

public ListNode partition(ListNode head, int x) {
        if(head==null||head.next==null)
            return head;

        ListNode small = new ListNode(-1);
        ListNode newsmallhead = small;
        ListNode big = new ListNode(-1);
        ListNode newbighead = big;

        while(head!=null){
            if(head.val<x){
                small.next = head;
                small = small.next;
            }else{
                big.next = head;
                big = big.next;
            }
            head = head.next;
        }
        big.next = null;

        small.next = newbighead.next;

        return newsmallhead.next;
}

Leetcode-Unique Paths II(Java)

Question:

Follow up for “Unique Paths”:

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]

The total number of unique paths is 2.

Note: m and n will be at most 100.

Thinking:

This question is similar with Unique Paths, and it’s the same methed to use dynamic programming. Only one difference is that we should check if it’s a obstacle. And if it’s a obstacle, its value of dp should be 0.

Solution:

public class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int lr = obstacleGrid.length;
        if (lr == 0)
            return 0;
        int lc = obstacleGrid[0].length;
        int[][] dp = new int[lr][lc];
        if (obstacleGrid[0][0] == 1){
            return 0;
        }
        dp[0][0] = 1;

        for (int i = 1; i < lr; i++){
            if (obstacleGrid[i][0] == 1)
                break;
            dp[i][0] = 1;
        }
        for (int i = 1; i < lc; i++){
            if (obstacleGrid[0][i] == 1)
                break;
            dp[0][i] = 1;
        }

        for (int i = 1; i < lr; i++)
            for (int j = 1; j < lc; j++){
                if(obstacleGrid[i][j] == 1)
                    continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }

        return dp[lr-1][lc-1];
    }
}