Brush title (1) - list

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/speargod/article/details/96903936

Basic

0.1 Routine

Written test, do not care about the space complexity, various auxiliary structures directly on, the sooner the better to write
the interview, the pursuit of time complexity O (n) space complexity O (1)

0.2 Basic Operation (represented, insert, delete)

Said insert, delete

struct listnode{
	int val;
	listnode *next;
	listnode(int _val,listnode *_next): val(_val),next(_next){}
}; //表示

p->next = p->next->next;  //删除了p-》next

copy_cur = new node(cur->label);
copy_cur->next =cur->next;
cur->next = copy_cur;  //这3步插入新节点 插在cur之后

tips: when it comes to the delete operation, we must consider the empty table, delete the header, at moderate operating table

Pointer p1 slow down a fast step 2 steps down the pointer p2

node *p1 = root;
node *p2 = root;
while(p2->next && p2->next->next){
	p1 = p1->next;
	p2 = p2->next->next;
}

The effect is p1 went to the midpoint, if the total number is an even number p1 came to the middle of the first two, p2 came to a final one
, if the total number is an odd number, came to the middle of the p1, p2 came to the last one.

1. Reverse list (important)

Title Description

After entering a list inverted list, the new list of the output header. (Source prove safety offer 24) (non-head node)

a) iteration ideas

Idea: We want to modify the next pointer member of each node, so every time to modify the current cur the next, pointing to pre (so remember pre), and also to remember the next node cur.
Method Memory : pre, cur, after three pointers.

Code

//第一种方法是:非递归方法
//设计好代码后 要考虑的特殊情况nullptr 一个节点 多个节点

listnode *reversenode(listnode *phead){
	listnode *pre=nullptr, *cur=phead, *after = nullptr;
	while(cur != nullptr){
		after = cur->next;    //保存当前的下一个
		cur->next=pre;        //调整当前next
		pre = cur;            //前一个前进
		cur= after;           //当前前进
	}                      
	return pre;
}

b) recursive method

tips: do not clever, so easy. Big problems, small problems, and do their own thing on the ojbk

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        //如果链表为空或者链表中只有一个元素
        if(pHead==NULL||pHead->next==NULL) return pHead;
         
        //先反转后面的链表,走到链表的末端结点
        ListNode* pReverseNode=ReverseList(pHead->next);
         
        //再将当前节点设置为后面节点的后续节点
        pHead->next->next=pHead;
        pHead->next=NULL;
         
        return pReverseNode;
         
    }
};

It has a head node

Nothing special, is to first check the head node is empty it, and then let the head of the list after the head node point reversal

listnode *reversnode2(listnode *phead){
	if(!phead)
		return phead;
	
    listnode *pre=nullptr, *cur=phead->next, *after = nullptr;
	while(cur != nullptr){
		after = cur->next;    //保存当前的下一个
		cur->next=pre;        //调整当前next
		pre = cur;            //前一个前进
		cur= after;           //当前前进
	} 
	phead->next = pre;
	return phead;
}

Reverse doubly linked list

There is no special, we know there is such a thing, next pointer and two members of the pre-exchange on the line

2. merge the two sorted list (important)

Title Description

Two monotonically increasing input list and output list after synthesis of two lists, of course, after that we need to meet synthesis list - decreasing the rules. (Source prove safety offer 25)

Iterative version of the idea

We need three pointers, pointer a, b is used to track the two lists, a pointer used to point c after the last node in the list, we merge, so that when we compare a, b point node size, so that the next point c the result of the comparison, you can. If there is a linked list in the end, then the list directly to the other element added to the combined list. In the specific implementation process, we puppet node (common trick the list), root to operate by a set, its role is to allow the synthesis of new chain has a place to start. The value of this node are free, we finally returned, in fact root.next;

Code

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
		using node = ListNode;
		 //新建一个头节点,用来存合并的链表。
		node root = node(0);
		node *cur = &root;
		while(pHead1 && pHead2){
			if(pHead1->val < pHead2->val){
				cur->next=pHead1;
				pHead1=pHead1->next;
			} else{
				cur->next=pHead2;
				pHead2 = pHead2->next;
			}
			
			cur=cur->next;
		}
		 //把未结束的链表连接到合并后的链表尾部
		if(pHead1)
			cur->next=pHead1;
		if(pHead2)
			cur->next=pHead2;


		return node.next;

    }
};

Recursive version ideas

Compare two head node size to give a true head node phead (smaller), then recursively processing small problem, plus some operations (the result phead the big problem with the results of small problems all together, return phead, recursive If the outlet of which one node is empty, return directly to the other)

Code

//递归版本 //
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(!pHead1)
			return pHead2;
		if(!pHead2)
			return pHead1;
		ListNode* p=nullptr;
		if((pHead1->val)< (pHead2->val)){
			p=pHead1;
			p->next = Merge(pHead1->next,pHead2);
		}
		else{
			p=pHead2;
			p->next = Merge(pHead1,pHead2->next);
		}
		return p;
			
    }
};

3. The print head from the end of the list

Title Description

Enter a list, the value returned by a ArrayList list sequentially from the tail to the head. (Source prove safety 6)

Thinking

Using the stack (simple question)

Code

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
       stack<int> sta;
	   vector<int> res;
	   while(head){
		   sta.push(head->val);
		   head=head->next;
	   }
	   
	   while(!sta.empty()){
		   res.push_back(sta.top());
		   sta.pop();
	   }
	   return res;
    }
};

4. penultimate linked list node k (important)

Title Description

Input a linked list, the linked list output reciprocal k-th node. (Source prove safety 22)
simple but important

Thinking

Pointer speed, note the inverse of the k-th node, the pointers go fast step k-1, instead of k steps, and k = 0 Note that the boundary problem head and a null pointer, there is the case if the length of the list is less than k

Code

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
		// 认为k==0是个无效的东西
		if(!pListHead || k==0)
			return nullptr;
		using node = ListNode;
		node * cur= pListHead;
		for(int i=0;i<k-1 && cur;++i){
			cur=cur->next;
		}
		//链表的长度小于k的情况
		if(!cur)
			return nullptr;
			
		//想象一下k=1 可以写出代码
		node * res = pListHead;
		while(cur->next){
			cur=cur->next;
			res=res->next;
		}
		
		return res;
    }
};

The replication complex list

Title Description

A complex input list (each node has a node value, and two pointers, one pointing to the next node, a special pointer to any other node), returns a value after the head of the list replication complex. (Note that the output results do not return parameter node reference, otherwise the program will return empty sentenced questions directly) (Source prove safety 35)

Thinking

Two solutions:
1. memory hash table
2. The chain double, setting the pointer, and finally disconnected.

@ 1 Solution: Hash time O (n) space O (n) //
twice traversed.
Traversing each node of the first copy, and put together with the hash table.
The second pass, took the copy associated set of random next copy

Hash code

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/

class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(!pHead)
			return nullptr;
		
		using node = RandomListNode;
		unordered_map<node*,node *> dict;
		node *cur=pHead;
		while(cur){
			dict.insert({cur,new node(cur->label)});
			cur=cur->next;
		}
		
		cur=pHead;
		while(cur){
			dict[cur]->next=dict[cur->next];
			dict[cur]->random=dict[cur->random];
			cur=cur->next;
		}
		return dict[pHead];
    }
};

Solution 2 code

  1. Traversing the nodes, each gave a value interpolated back to exactly the same as the new node
  2. This once again traverse the node and then two steps, the random gave each new node to get
  3. Finally, the list to open. (Note that several boundary conditions)
    time O (n) space O (1)
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead ==nullptr)
            return nullptr;
        return core1(pHead);

    }
//让原链表 double
    RandomListNode*  core1(RandomListNode* pHead){
        using node = RandomListNode;
        node * cur = pHead;
        node* copy_cur=nullptr;
        while(cur){
            copy_cur = new node(cur->label);
            copy_cur->next =cur->next;
            cur->next = copy_cur;  //这3步插入新节点
            cur = copy_cur->next;  //向下走
        }
		
//复制节点的  random		
        cur = pHead;
        copy_cur = pHead->next;
        while(cur){
		
            if(cur->random){  //避免random指向空
                copy_cur->random = cur->random->next;
            }
            cur = copy_cur->next;
            if(cur != nullptr) // 再次注意边界
                copy_cur = cur->next;
        }
//拆分链表        
        cur = pHead;
        copy_cur = pHead->next;
        node * copy_head = copy_cur;
        while(cur){
		 //cur和copy的拆分都需要!
            cur->next = copy_cur->next;  //拆 cur
            cur = cur->next;  // cur往下移动
			
            if(cur != nullptr)  // 注意边界
                copy_cur->next = cur->next;  // 拆copy
            copy_cur =copy_cur->next;    // copy移动
        }
        
        return copy_head;
        
    }

};

6. Delete list node

Title Description

Order to delete the node to the head pointer list and a node pointer in O (1) time (to prove safety source 18)

Thinking

Because the requirements are O (1), and is a singly linked list, it is proposed a new method for "replacing"

  1. If the node is not the end node, then the value may be directly assigned to a node of the node, then enabling the next node pointing to the next node, the next node is deleted, the time complexity is O (1).
  2. If it is the end node, but the entire list, only this one node, then delete
  3. If you list more than one node, you need to traverse the list to find the previous node, and then let a node point before nullptr, and then delete, time complexity is O (N).
    ps. After delete, do not forget to set nullptr (to regulate)

Code

void core(node **head,node *del ){
    //如果是空指针
    if(!head || !del)
        return;
    
    //要删除的del不是尾结点
    if(del->next){
        node * res =del->next;
        del->val=res->val;
        del->next=res->next;
        
        delete res;
        res=nullptr;
    } 
    else if(*head ==del){ // 只有这一个指针
        delete del;
        del=nullptr;
        *res=nullptr;
    }  
    
    else{     // 有多个节点,并且是尾结点,遍历找到前一个
        node *cur = *head;
        while(cur->next != del){
            cur=cur->next;
        }
        
        cur->next=nullptr;
        delete del;
        del=nullptr;
    }
    
}

7. Delete duplicate node list

a) retain the version
Title Description

In a sorted linked list nodes duplicate, delete the duplicate node list, the node repeats a reservation, the head pointer list returned. For example, list 1-> 2-> 3-> 3-> 4-> 4-> 5 workup 1-> 2-> 3-> 4-> 5
tips: This is a reserved version, and sorted the

Thinking

A pre nodes and the current node node traversal save on cur

  1. If the current node and a node on the same value, then a delete operation is performed on cur does not advance and pre, cur proceeds.
  2. If the two are different forward

Code

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
		if(!pHead) return nullptr;
		ListNode* pre = pHead;
		ListNode* cur = pHead->next;

		while(cur){
			if(pre->val==cur->val){
				pre->next = cur->next;
				cur=cur->next;
			}
			else{
				pre =cur;
				cur=cur->next;
			}
		}
		return pHead;
    }
};

b) does not retain version
Title Description

In a sorted linked list nodes duplicate, delete the duplicate node list, the node does not retain repeated, returns the head pointer list. For example, the list 1-> 2-> 3-> 3-> 4-> 4-> 5 is treated 1-> 2-> 5
tips: This version is not retained, still sorted the

Iteration

Because there duplicate nodes should be deleted, so it is possible to head node must be deleted.
So for convenience, we first let's add a puppet node root, in order to facilitate the first encounter, the second node on the same situation
and we have been directed to ensure that p is not a repeat of the last node, so we let p point to root, traversing

  1. If p- "val next of == p-" next- "next of val, then began to eliminate, we write down the value of dup, deleted until p-" next val is not equal to dup or equal nullptr the next date
  2. If unequal, then p to move back

Code

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        using node = ListNode;
        if(!pHead || !pHead->next)
            return pHead;
        
        
        node temp(0);
        node *root=&temp;
        root->next=pHead;  // 首先添加一个傀儡节点,以方便碰到第一个,第二个节点就相同的情况
        
        node *p=root;
 
        int dup;
        while(p->next && p->next->next){
            
            //如果当前cur有下一个 且下一个跟cur值一样,那么
            if(p->next->val== p->next->next->val ){
                dup=p->next->val;
                while(p->next && p->next->val== dup){
                    p->next=p->next->next;  //直到p-》next的val是个新值为止 or 指向nullptr。
                }
            }
            else p=p->next;
        }
        
        return root->next;
    }
};

Recursive version

Well understood

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
		// 只有0个或1个结点,则返回
		if(!pHead || !pHead->next)
			return pHead;
		
		// 当前结点是重复结点
		if(pHead->val == pHead->next->val){
			ListNode * cur = pHead->next;
			
			while(cur && cur->val == pHead->val){
				cur =cur->next;
				
			}// 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
			return deleteDuplication(cur);
			// 从第一个与当前结点不同的结点开始递归
		}
		// 当前结点不是重复结点
		else{
			// 保留当前结点,从下一个结点开始递归
			pHead->next = deleteDuplication(pHead->next);
			return pHead;
		}
    }
};

8. singly linked list a series of problems that intersect (important !!!)

Two-way linked list, find the first point of intersection, which is actually three questions !!!

  1. How to determine whether there is a chain ring and find the entrance ring
  2. How to find the node 2 single chain acyclic first intersection
  3. How to find the two rings have a single list of intersection node
    tips: (if there is a ring, a loop-free, two-way linked list (as a singly linked list) may not intersect)

Here just write ideas: a complete analysis

Question 1: How to determine whether there is a chain ring and ring to find the entrance of
a slow go one step each time the pointer p1, p2 pointer to a fast walk every step 2, if no ring, fast pointer is necessarily the end of next encounter is nullptr, that direct return nullptr, if there is a ring that p1 and p2 will definitely meet in the ring in a location. This time the pointer quickly back into position at the beginning of the list, and each time step, while slow pointer also go one step further from that encounter each position, the last two pointer position must meet the entrance ring

Question 2: How to find the node 2 single chain acyclic first intersect?
Two single chain acyclic, if the intersection, it can be Y-shaped
so the process is to find
the list to the end of a traversing node end1, while the recording dots len1 summary
list traversal to the end node end2 2, while the recording dots are summarized len2
Comparative end1 and end2, nullptr a return are not equal, the next step is equal to enter
the large len list, if the list is 1, go len1-len2 step,
then go with two lists, one of the two nodes is equal to the first result is a first intersecting nodes.

Question 3: How to find the two rings have a single list of the first intersection node?
Divided into three cases
1) two inlet rings are equal then the overall shape of a Y + ring,
this problem just like the case 2, similar to the first two acyclic intersection node, but now is the inlet end of the ring
2) two inlet rings unequal, and two disjoint lists,
ranging from the inlet 3) of the two rings, but the intersection of two lists, that is, from the shape of a ring topology, the separation of the two lines, so that the first intersection point is any one of two inlet rings

9. Print ordered list of two common portion

Only ideas

The process is similar to merge, starting from their starting point, which is a small value, step forward, it is the same as print
(source left God)

10. The list is determined whether a palindrome

Title Description

1221 12331 palindrome is not a palindrome
(Source left God)

Thinking

Use auxiliary space:
With a stack traverse the list to keep the value on the stack
and then traverse a linked list while compare with the top element, not the same as it returns false, as the pop-up, a relatively lower

Without the use of auxiliary space:
Fast take two steps pointer, pointer slow step, to the intermediate position of that node, and the node to which a half after the reversal, and start from both ends of the comparison, the same one, the false different ratio, while the final it reversed back to the second half of the node.

java代码
	// need O(1) extra space
	public static boolean isPalindrome3(Node head) {
		if (head == null || head.next == null) {
			return true;
		}
		
		
		//快指针走两步,慢指针走一步,来到中间那个节点位置
		
		Node n1 = head;
		Node n2 = head;
		while (n2.next != null && n2.next.next != null) { // find mid node
			n1 = n1.next; // n1 -> mid
			n2 = n2.next.next; // n2 -> end
		}
		
		
		//反转后半部分链表
		
		n2 = n1.next; // n2 -> right part first node
		n1.next = null; // mid.next -> null
		Node n3 = null;
		while (n2 != null) { // right part convert
			n3 = n2.next; // n3 -> save next node
			n2.next = n1; // next of right node convert
			n1 = n2; // n1 move
			n2 = n3; // n2 move
		}
		
		//两端比较
		
		n3 = n1; // n3 -> save last node
		n2 = head;// n2 -> left first node
		boolean res = true;
		while (n1 != null && n2 != null) { // check palindrome
			if (n1.value != n2.value) {
				res = false;
				break;
			}
			n1 = n1.next; // left to mid
			n2 = n2.next; // right to mid
		}
		
		//把后半部分链表再恢复回来
		n1 = n3.next;
		n3.next = null;
		while (n1 != null) { // recover list
			n2 = n1.next;
			n1.next = n3;
			n3 = n1;
			n1 = n2;
		}
		return res;
	}

11. The list is divided about section

Title Description

The one-way linked list by a certain value divided into small left, center equal to the right of the large form
(source left God)

Thinking

Auxiliary space
Array put it back again inside the partition and then a series (or directly in the original list to which the changed values).
Without the use of auxiliary space
6 to change the pointer respectively corresponding to less equal more
start and end points, then traverse the list, the respective nodes fill it up, the last three zones joined end to end

12. The single list two lists to generate a sum

Title Description

937 and 63 generate 1000
(left God source)

Thinking

A method string into two strings 93763 obtained by adding 1000 to generate the list (the number is too large to prevent the string, int overflow)
method of directly adding 2 reverse two lists, then the new list in reverse order, to

Guess you like

Origin blog.csdn.net/speargod/article/details/96903936