Showing posts with label Algorithm. Show all posts
Showing posts with label Algorithm. Show all posts

Wednesday, August 24, 2016

Advance Tree Algorithm 1 Summary - Leetcode


1. Serialization

[Method 1] pre-order+in-order or in-order+post-order
[Problem] same nodes will cause problems in deserialization.
e.g., pre-oder = [5,5,5,5], in-order = [5,5,5,5] ->no way to figure out what exactly the tree looks like.

[Method 2] level-order serialization
    
[1,2,3,4,null,5,6,null,null,null,null]
(You can also trim all the "null" in the end)

    

2. Binary Search Tree 

1. Predecessor and Successor





java.util.TreeMap support API ceiling(value) and floor(value)
[Question]
270. Closest Binary Search Tree Value

2. other BST questions

222. Count Complete Tree Nodes
230. Kth Smallest Element in a BST

Tuesday, August 23, 2016

Compare DFS and BFS


BFS Summary - Leetcode

0.Basic Concepts

Breadth First Search (BFS) is a method for traversing or searching tree or graph data structures.


1.When do we apply BFS?

It is frequently used to
  1) explore some features/characteristics in the tree/graph.
     [typical examples]
        [101] Symmetric Tree
        [261] Graph Valid Tree

  2) search for nodes/level/connected components
     [typical examples] search for nodes/connected components
        [133] Clone Graph
        [200] Number of Islands
        [323] Number of Connected Components in an Undirected Graph
        [286] Walls and Gates

     [typical examples] level related problem
        [102] Binary Tree Level Order Traversal
        [103] Binary Tree Zigzag Level Order Traversal
        [107] Binary Tree Level Order Traversal II
        [199] Binary Tree Right Side View

  3) shortest steps(path) 

     Utilizing BFS to find the shortest path involves a lot of details, so let's use an example to discuss it.


Example:



The solution needs to:
1)Utilize a matrix (int[][] distance) to record the shortest distance from node A to node (i, j). If we cannot reach the node (i, j), marked it as -1. 

2)Apply BFS to calc distance[][]. All distance[i][j] except the the start point should be initialized as -1; the start point distance is initialized as 0.




3)When updating the distance matrix using BFS, for each dequeued node, we will enqueue its unvisited grass neighbor (which means distance of an obstacle will always be -1. This also makes sense because -1 means unreachable):

Here we show the pseudo codes for this BFS process (which is also classical BFS codes):

Follow-up 1:

What if we can move in 8 directions? (up, upright, right, ...)

If you run the above code, you will meet a bug like this:

Why?
In the round 0, you dequeue A, and enqueue all nodes around A, which are (0,0), (0,1), (1,1), (2,1), (2,0)

In the round 1, you first dequeue (0,0), as we can see, for (0,0), its unvisited neighbors are (0,1), (1,1), so you will enqueue these two nodes.

This means in the round 2, you will pop (0,1) and (1,1) again, and set their distances value as 2.



Now we see our problem:
If the nodes in the queue can be each other’s neighbors, the neighbor can be added to the queue again, which will cause wrong distance.

How to solve it?
distance[i][j] == -1 means this node is unvisited. So before we update node (i,j)’s distance value, check whether distance[i][j] == -1

So we new code is:





Follow-up 2:

If we want to find the minimum path, rather than only find the minimum steps to from one node to another, how to achieve this?
There are two ways:

1. We can store Tuple<Node, Path> into the queue. -> O(n^2)

2. We can use BFS to find how long is the shortest path (assume k). Then we apply DFS to find the path (because we know path length = k, for a path longer than k, we can stop earlier). -> O(n), but DFS has stack overflow problem.

[typical questions]
        [111] Minimum Depth of Binary Tree
        [126] Word Ladder II
        [310] Minimum Height Trees

        [317] Shortest Distance from All Buildings







Friday, August 12, 2016

Binary Search Summary - Leetcode

1.Definition

Binary Search is a search algorithm that finds the position of a target value within a sorted array (or an array arranged in a special way).

2.Methods

The key point of binary search is to maintain a range and make sure the target number is in the range. The search process is to shrink the range in multiple iterations until its size is 1 or find it.
In each iteration, half (or 1/n) the range's size. Use the middle element's value to decide it is the left half range or the right half range.

3 key steps:
1) identify the range (sometimes we might need to construct the range)
2) decide the appropriate way to shrink the range
3) check potential endless loops

e.g., find the index of 5 in the array 0-9

Note: We can use two pointers (lo, hi) to represent the range.

3.When do we apply binary search? 

1.Index-based search problem: 3 basic BS problems and corresponding methods to shrink the range. 

[question] Given a sorted array/matrix, try to find a specific element.

[identify the range] In this kind of question, the range is the index range [0, arr.length-1].

[methods of shrinking the range]
We will discuss how to shrink the range in the 3 types of BS problem. Let's assume that the current range is [lo, hi], and mid = lo+(hi-lo)/2.

[type 1] Find the only/any one problem
[Typical example]: find the index of 5 in the array [0,1,2,3,4,5,6]
[Explain]:
if array[mid] < target, shrink the range as [lo, mid-1];
else array[mid] > target, shrink the range as [mid+1, hi];
else return mid;

[Questions]
74. Search a 2D Matrix
240. Search a 2D Matrix II
374. Guess Number Higher or Lower

[type 2] Find the first one
[Typical example]: find the index of the first 5 in the array [0,1,1,1,2,3,4,5,5,6]
[Explain]:
if array[mid] == target, shrink the range as [lo, mid]; //*
else if array[mid] < target, shrink the range as [mid+1, hi];
else shrink the range as [lo, mid-1];

//* It is possible to trigger an endless loop. So we need to check whether lo==mid, if it is, break and jump out of the loop.

[Questions]
153 Find Minimum in Rotated Sorted Array
35 Search Insert Position
275. H-Index II
278. First Bad Version

[type 3] Find the last one
[Typical example]: find the index of the last 5 in the array [0,1,1,1,2,3,4,5,5,6]
[Explain]:
if array[mid] == target, shrink the range as [mid, hi];
else if array[mid] < target, shrink the range as [lo, mid-1];
else shrink the range as [mid+1, hi];

[type 4 - combination type] questions involves two or three types above

153 Find Minimum in Rotated Sorted Array
154. Find Minimum in Rotated Sorted Array II
33. Search in Rotated Sorted Array
81. Search in Rotated Sorted Array II
34. Search for a Range


2.Advanced binary search: shrink the range in a specific way

[calculation problem] 

[Identify the range]: given a number n, the range is [0,n]
tips: >>1 <<1 corresponds to /2, *2, which can be used in binary operations.
[questions]
367. Valid Perfect Square
29. Divide Two Integers
69 Sqrt(x)
50. Pow(x, n)
287. Find the Duplicate Number


[Other typical array/matrix related binary search problem]

302. Smallest Rectangle Enclosing Black Pixels
[key point]
1. [identify the range]: contstruct an array, array[i] represents in the column i of the matrix, there is at least one 1. the array will be like [00011111000].
2. [methods of shrinking the range]: find the first 1's and last 1's index.

354. Russian Doll Envelopes

4. Median of Two Sorted Arrays
1.[identify the range] the range contains two sorted array, [arr1] and [arr2]
2.[methods of shrinking the range]:
   

363. Max Sum of Rectangle No Larger Than K

162. Find Peak Element


[Other related questions]

300. Longest Increasing Subsequence
209. Minimum Size Subarray Sum
378. Kth Smallest Element in a Sorted Matrix
349. Intersection of Two Arrays
350. Intersection of Two Arrays II



Wednesday, August 3, 2016

Advance Tree Algorithm 2 Summary - Leetcode

Union-Find with Path Compression


Problem Description: Find All Disjoint Sets

Idea:

1.Build roots array:

If we can build the root array as shown in the fig, we can find the root of a node. Two nodes belong to the same set if they share the same root.
(Note: The root's parent is the root itself. e.g., node 5's parent is node 1. Node 1's parent is node 0. Node 0's parent is 0. So node 0 is the root of node 5.) 

2.Path compression
Because we only care about the root of a node, so rather than store its parent, it is better to store its root in the array. To achieve this, we need to implement path compression.


Key Points:

1.Use Array to represent a tree/graph.
2.Path compression

A very good tutorial:
https://www.youtube.com/watch?v=ID00PMy0-vE

Basic Algorithm:

-------------------------------------------------------------
public union_find(int[] edges, int n){
  //n indicates node 0~node n-1
  int[] roots = new int[n];
  for(int i=0;i<n;i++) roots[i] = i;    //i indicates node i
    //use "int[] roots" to construct a tree. roots[i] represents node i's parent (root if using path compression)

  for(int[] edge: edges){
    int root1 = find(edge[0], roots);                        
    int root2 = find(edge[1], roots);                        
    if(root1!=root2) merge(root1, root2, roots);             
  }
}

private int find(int node, int[] roots){
  if(node==roots[node]) return node;
  else{
    roots[node] = find(roots[node],roots); //path compression
  }
return roots[node];
}

private void merge(int root1, int root2, int[] roots){
  roots[root1]=root2;
}

-------------------------------------------------------------
Questions:
[323] Number of Connected Components in an Undirected Graph
[261] Graph Valid Tree

Advanced

If nodes cannot be represented as 0,1,2,3 ... (a continuous sequence), we can use a map, giving each node an id.

Questions:
[128] Longest Consecutive Sequence

Topological Sorting

Problem Description

Input: a directed graph
Output: an ordered array of nodes. (Requirement: If there is an path (0->1) in the graph, the result array should put node 0 in front of 1.)


1.Topological sorting based on DFS

1)Idea



Start from any node and do DFS. When the node has not been visited yet, its status is 0. When the node is being visited (or its descent is being visited), the node's status is 1. When the node's all descent have been visited, the node's status is 2. And it is the time to put the node into the stack.

Considering the node's descents will always be put into stack before itself, the output ordered array is the sequence of the nodes in the stack from the top to the bottom.

2) How about the loop?

When you meet a node which is being visited (status = 1), what does it mean? YOU MEET A LOOP in the graph. Under such situations, there won't be a valid output. You might want to throw an exception now!

3) Key points

Hashmap: (int[] array) stores nodes' status.
Stack: stores the visited nodes.
DFS

4) Basic Algorithms

-----------------------------------------------------------
public int[] potologicalSort(int[][] edges, int n) throws Exception{
    //n indicates node 0~node n-1
    List<List<Integer>> graph = buildGraph(edges, n);
    int[] visited = new int[n];
    Stack<Integer> stack = new Stack<>();

    for(int i=0; i<n; i++){
        //If the node is in the loop (being visited)
        //If the node has not been visited, do dfs
        if(visited[i]==1) throw new Exception("There is a loop in the graph");
        else if(visited[i]==0) dfs(i, graph, visited, stack));
    }

    int[] result = new int[n];
    int i=0;
    while(i<n) result[i++]=stack.pop();
    return result;
}

private void dfs(int node, List<List<Integer>> graph, int[] visited, Stack<Integer> stack) throws Exception{
    visited[node] = 1;
    for(int i:graph.get(node)){
        //do dfs on all children of the node
        if(visited[i]==1) throw new Exception("There is a loop in the graph");
        else if(visited[i]==0) dfs(i, graph, visited, stack));
    }
    visited[node]=2;
    stack.push(node);
}

private List<List<Integer>> buildGraph(int[][] edges, int n){
//build the adjacency list of a graph
}
-----------------------------------------------------------

2.Topological sorting based on BFS

1) Idea

A node's fan-in: is the number of the node's parents (source node). e.g., in the graph, node 2's fan-in is 1, because it has a source node 0. Node 3'2 fan-in is 2 because it has 2 source nodes (node 1 and 2). Node A's fan-in = 0 means there is no node pointing to A.


The algorithm initializes the queue with all the node with fan-in=0. After we poll a node from queue, we update its children's fan-in table. Each child's fan-in -= 1. If the fan-in = 0, we add the child into the queue. So the queue maintains node collections whose fan-in = 0. The algorithm stops when there is no node in the queue.

2) How about the loop

We compare the number of nodes we visited (BFS) and the total number of nodes. If they are equal, there is no loop. Otherwise, there is a loop.

3) Key points

Queue: stores nodes with fan-in=0
HashMap: stores all nodes' fan-in number
BFS

4) Basic Algorithms

-----------------------------------------------------------
public int[] topologicalSort(int[][] edges, int n) throws Exception{
    Map<Integer, List<Integer>> graph = new HashMap<>();

    Queue<Integer> fanin0 = new LinkedList<>();
    Map<Integer, Integer> status = new HashMap<>();
 
    init(edges, n, graph, fanin0, status);

    List<Integer> result = new ArrayList<>();

    while(!queue.isEmpty()){
        int len = queue.size();

        //for all nodes whose fanin=0
        for(int i=0;i<len;i++){    
            int node = queue.poll();
            result.add(node);
         
            //for each child, update its fanin number, and if it is 0, add to queue fanin0
            for(int child:graph.get(node)){
                int fanin = status.get(child)-1;
                if(fanin==0) fanin0.add(child);
                status.put(child, fanin);
            }
        }
    }

    if(result.size()!=n) throw new Exception("there is a loop!");
    return toArray(result);
}

private void init(...){ ... }
private int[] toArray(...) { ... }
-----------------------------------------------------------

Compare topological sorting based on BFS and DFS

The BFS method has one advantage, compared to DFS. It can sort nodes without path order constraints, according to other ordering rules. (It is difficult to understand this, let's see the following example)

Given a directed graph (all nodes are represented by int), output an ordered array of nodes.

The requirement is:
Constraint1: If there is a path (0->1) in the graph, the result array should put node 0 in front of 1.
Constraint2: For two nodes which do not have constraint 1, the smaller node should be in front of the larger node in the output array

The output should only be: [0,1,2,4,3]
We cannot output [0,2,1,4,3]

Solution:
in the bfs method
---------------------------------------------------
    while(!queue.isEmpty()){
        int len = queue.size();
        Collections.sort(queue);
        //for all nodes whose fanin=0
        for(int i=0;i<len;i++){
---------------------------------------------------
Add one line, sort the queue. So all nodes with fan-in = k are sorted.

Questions:
[332] Reconstruct Itinerary
[207] Course Schedule
[269] Alien Dictionary


Index Tree
Segment Tree

Tree's Pre-Order, In-Order and Post-Order Traverse Summary

To traverse a tree, there r three basic ways: preorder, inorder and postorder. All the three methods can be implemented in recursion or non-recursion. Here to simplify the problem, we assume that the tree is a binary tree.

Recursion Traversal

It is easy to recursively traverse a tree.

1.Preorder: root->left->right
public traverse(TreeNode root){
    visit(root);
    traverse(root.left);
    traverse(root.right);
}

2.Postorder: left->right->root
public traverse(TreeNode root){
    traverse(root.left);
    traverse(root.right);
    visit(root);
}

3.Inorder traverse: left->root->right
public traverse(TreeNode root){
    traverse(root.left);
    visit(root);
    traverse(root.right);
}

Non-recursion Traversal

When implementing traversal using the non-recursive method, we might need some extra space (stack) to store some tree nodes. Morris Inorder Traversal presents a method to traverse a binary tree using O(1) space and O(n) time.

1.Preorder: root->left->right
Considering stack is the first-in-last-out Container, we should push the right node into stack before the left node so that the left node can be popped and visited earlier. //pop root, push right, push left

public traverse(TreeNode root){
    if(root==null) return ;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode node = stack.pop();   //visit the node
        if(node.right!=null) stack.push(node.right);
        if(node.left!=null) stack.push(node.left);
    }
}

2.Postorder: left->right->root
Postorder is similar the preorder, but "first pop the root, then push the left, then push the right". So the visiting is like "root, right, left". In the end, reverse the sequence, we can get "left, right, root".

public traverse(TreeNode root){
    if(root==null) return ;
    Stack<TreeNode> stack = new Stack<>();
    List<TreeNode> list = new ArrayList<>();
    stack.push(root);
    while(!stack.isEmpty()){
        TreeNode node = stack.pop();
        list.add(node);
        if(node.left!=null) stack.push(node.left);     
        if(node.right!=null) stack.push(node.right);  
    }
    for(int i = list.size()-1;i>=0;i--){
        visit(list.get(i));
    }
}

3.Inorder traverse: left->root->right

public traverse(TreeNode root){
    if(root==null) return ;
    Stack<TreeNode> stack = new Stack<>();
    List<TreeNode> list = new ArrayList<>();
    TreeNode cur = root;
    while(true){
        if(root.left!=null){
            stack.push(root);
            cur = cur.left;
        }else{
            if(stack.isEmpty()){
                break;
            }else{
                TreeNode parent = stack.pop(); //visit the node now
                cur = parent.right;
            }
        }
    }
}

Morris Inorder Traverse

public traverse(TreeNode root){
    if(root==null) return ;
    TreeNode cur = root;
    while(cur!=null){
        if(cur.left==null){    //visit the right node next;
             visit(cur);
             cur = cur.right;
        }else{
             TreeNode predecessor = cur.left;
             //find the Predecessor of the cur node.
             while(predecessor.right!=null && predecessor.right!=cur) predecessor = predecessor.right;
             if(predecessor.right==null){
                 //have not visited cur node's left tree, build the blue link in the graph
                 predecessor.right = cur;
                 cur = cur.left;
             }else{
                 //have visited cur node's left tree, remove the blue link in the graph
                 predecessor.right = null;
                 visit(cur);
                 cur = cur.right;
             }

        }
    }
}

Thursday, July 21, 2016

DFS Summary - Leetcode

0.Basic Concepts

Depth First Search (DFS) is a method for traversing or searching tree or graph data structures.

1.When do we apply DFS?

It is frequently used to
  1) explore some features/characteristics in the tree/graph.
  2) search specific nodes/paths/connected components(int the graph)

2. Typical Examples

Some tips:
1. A leaf node can only be represented as "node.left==null && node.right==null".


explore tree features:
[100] Same Tree
[101] Symmetric Tree
[104] Maximum Depth of Binary Tree
[110] Balanced Binary Tree

Search for specific node/connected components
[200] Number of Islands
[323] Number of Connected Components in an Undirected Graph

Path-related
[112] Path Sum
[129] Sum Root to Leaf Numbers
[337] House Robber III
[366] Find Leaves of Binary Tree

Related recursive problems
[105] Construct Binary Tree from Preorder and Inorder Traversal
[108] Convert Sorted Array to Binary Search Tree




Thursday, July 14, 2016

Dynamic Programming Summary - Leetcode

0.Basic Concepts

Dynamic Programming (DP): is a method for solving a complex problem by breaking it down into a collection of simpler subproblems, solving each of those subproblems just once, and storing their solutions - ideally, using a memory-based data structure.

1.The difference between DP and divide-and-conquer

Divide-and-conquer partitions the problem into disjoint subproblems while DP partitions the problem into overlapped subproblems.

2.Typical DP problems

  • A problem can have many solutions, each solution has a value, try to find the solution with optimal value.
  • Try to find the total number of solutions of a problem.

3.Solution

  1. Define the structure of an optimal solution.
  2. Recursively define the value of an optimal solution.
  3. Compute the value of an optimal solution in a bottom-up fashion.
    If we only need the value of the optimal solution, the above 3 steps are enough.
  4. Construct an optimal solution from computed information. (Usually, step 4 requires us to maintain some additional information to construct the optimal solution.)

4.Typical Examples (examples are all from Leetcode.com)

I strongly recommend you to read the following two articles: 



[Type 1] find the solution with optimal value 

  • [Type 1-1] Index-based based bottom-up method:
    [A typical question 1-1]
     Given an array arr[], find the continuous subarray which has the maximum sum, output the sum value.
    e.g., [1, -2, 3, 4, -2] -> 7 (becuase 3+4=7)

    [How to define dp[i]]

    The "optimal subsolution dp[i]" can be constructed in 2 ways:
        1.dp[i] is the optimal solution for the subarray arr[0:i]
        
    e.g., in the example, dp = [1,1,3,7,7]
        The output should be dp[arr.length-1], which is 7.

        2.dp[i] is the optimal solution whose last element is arr[i] for the subarray arr[0:i] 
        e.g., in the example, dp = [1,-1,3,7,5]
        The output should be maximum value in dp[], which is 7.
        (A brief explanation: dp[1]=-1 is because dp[1] must contain the lase element arr[1], so the subarray can be [1,-2] or [-2], apparently the first subarray's sum is larger. So dp[1] = 1+(-2) = 1.


    [Bottom up process]
    The bottom up process is from i=0 to i=arr.length-1. This is different from value-based problem. We will talk about this later.

    [Practice]
      • array:
      1. [53] Maximum Subarray
      2. [152] Maximum Product of Subarray
      3. [32] Longest Valid Parentheses
      4. [300] Longest Increasing Subsequence
      5. [368] Largest Divisible Subset
      6. [139] Word Break
      • matrix:
      1. [120] Triangle
      2. [64] Minimum Path Sum
      3. [221] Maximal Square
      4. [174] Dungeon Game (Note, from bottom right to top left)
      5. [354] Russian Doll Envelopes 
      6. [363] Max Sum of Rectangle No Larger Than K
      7. [32] Longest Valid Parentheses
  • [Type 1-2] Index-based bottom-up method, with multiple states.
    [Question 1-2]
     adds some extra constraints on type 1-1. The constraint might lead to multiple states. Sometimes, solution 1-1 could solve such situation. However, sometimes it does not work.

    [Solution 1-2]
     use extra arrays each corresponding to one condition. (Or add one dimension, e.g., array arr[] ->matrix arr[][], dp[i][0] corresponds to state 0, dp[i][1] corresponds to state 1, etc).

    [Practice]
      1. [198] House Robber
        ([soln], two states: rob the first house/not, the bottom-up method needs to maintain 2 arrays, one corresponding to "rob the 1st house", another corresponding to "not rob the 1st house". Similarly, we can also maintain a matrix arr[][], arr[i][0] corresponds to "not rob the first house" while arr[i][1] corresponds to "rob the first house".)
      2. [213] House Robber II
      3. [256] Paint House (3 states/colors)
      4. [265] Paint House II (k states/colors)
      5. [276] Paint Fence
      6. [123] Best Time to Buy and Sell Stock III
      7. [188] Best Time to Buy and Sell Stock IV
      8. [309] Best Time to Buy and Sell Stock with Cooldown
         dp[start][end] variation: The substructure (subarray) is arr[start:end] rather than arr[0:end]. We can understand in this way: A subarray ending at j can starts from i = 0 to j-1. Each i corresponds to a state. So we should construct dp as dp[i][j], which represents the optimal solution for subarray[i:j].
      1. [132] Palindrome Partitioning II
      2. [87] Scramble String
      3. [312] Burst Balloons
  • [Type 1-3] Value-based bottom-up method
    [A typical q
    uestion 1-3] "Given a number n and an array arr[], try to find the minimum set of numbers from arr whose sum is equal to n".

    [How to define dp[i]] dp[i] corresponds to the optimal set whose sum is equal to i.

    [Bottom up process] The bottom up process is from i=0 to i=n. This is the biggest difference between index-based problem and value-based problem. In the index-based problem, the bottom up process is from i=0 to i=arr.length-1.

    [Practice]
      1. [322] Coin Change
      2. [279] Perfect Squares
      3. [343] Integer Break

[Type 2] Two arrays "match" DP 

This type of questions will give two strings, s1 and s2. The question is whether s1 can be transformed/matched to s2 in a given way. The typical solution is to construct a m*n matrix, check whether s1[:i] can be transformed/matched to s2[:j]. Construct the matrix in a bottom-up way.

[Practice]

[Type 3] total # of solutions

Thursday, May 26, 2016

LinkedList Summary - Leetcode

Coding interview questions about LinkedList mainly can be divided into the following 3 kinds:
1.Basic operations to a single list including add, delete, access and change.
2.reorder a list
3.Partition and merge

Basic operations to a single list

access

160. Intersection of Two Linked Lists
142. Linked List Cycle II (two pointer)
141. Linked List Cycle (two pointer)
About problems using two pointers, pls read my another blog CS Interview - Two Pointer.

delete

237. Delete Node in a Linked List
83. Remove Duplicates from Sorted List
82. Remove Duplicates from Sorted List II
19. Remove Nth Node From End of List

[solution key]
1.dummy node
2.triple <prev, cur, next>

[explanation]
Once the question requires removing a node from a linked list, it is possible that the head of the list is removed. Thus, we need a dummy node which prepends the list.
    dummy = ListNode(0)
    dummy.next = head

If we use "cur" to represent the "delete node", before we do deletion, we need to record the node before the "cur" and the node after "cur", which are indicated as "prev" and "next".
Thus, the deletion process can be written as:
    pre.next = next
This form is not fixed. It can be "cur.next = cur.next.next". It also can be "cur.next = prev" if we want to reverse the link. But basically, we need the triplet <prev, cur, next> to change the link.

[example]
83. Remove Duplicates from Sorted List
[Question]
Given a sorted linked list, delete all duplicates such that each element appear only once. For example, Given 1->1->2, return 1->2. Given 1->1->2->3->3, return 1->2->3.
[Solution]
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """

        #define dummy
        dummy = ListNode(0)
        dummy.next = head
   
        pre = dummy
        cur = head
        while cur:
            val = cur.val
            #change the link
            while cur.next and cur.next.val ==val:
                cur.next = cur.next.next
            #move to next iteration
            pre = cur
            cur = cur.next
        return dummy.next

Reorder a list
Reorder the list given the requirement
234. Palindrome Linked List
206. Reverse Linked List
92. Reverse Linked List II
143. Reorder List
61. Rotate List
25. Reverse Nodes in k-Group
24. Swap Nodes in Pairs

Reordering is to adjust links among nodes. When changing a node's position, we need to record the nodes before and behind the changed node, and rebuild the links accordingly.

Sort
147. Insertion Sort List
148. Sort List
Sorting, in fact, is a special reordering method.

Partition and merge

328. Odd Even Linked List
86. Partition List
23. Merge k Sorted Lists
21. Merge Two Sorted Lists

When partitioning a linked list to two, pay attention to the last nodes. Break their original links to assign their next nodes as "None".

e.g.,
[question]
86. Partition List
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->3->4->5->2->6 and x = 4,
return 1->3->2->4->5->6.

[solution]
1.first partition the list to two lists: 1->3->2 and 4->5->6


2.concat the two lists

[code]
class Solution(object):
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        dummyS = ListNode(-1)
        small = dummyS
        dummyL = ListNode(1)
        large = dummyL
     
        cur = head
        while cur:
            if cur.val<x:
                small.next = cur
                small = small.next
            else:
                large.next = cur
                large = large.next
            cur = cur.next

        small.next = dummyL.next
        large.next = None
        return dummyS.next