Force deduction linked list - Simple (double pointer, array list, recursion, speed pointer)

Give you the head node of a single linked list head,Please judge whether the linked list is a palindrome linked list
Title Description:
Example 1:
Example 2:
Tips:
Advanced:

234. Palindrome linked list

Title Description:

Give you the head node of a single linked list   head, Please judge whether the linked list is a palindrome linked list. If yes, return   true  ; Otherwise, return   false  .

Example 1:


Input: head = [1,2,2,1]
Output: true

Example 2:


Input: head = [1,2]
Output: false

Tips:

The number of nodes in the linked list is within the range [1, 105]
0 <= Node.val <= 9

Advanced:

Can you use it   O(n) time complexity and O(1) space complexity solve this problem?

I don't think this problem is difficult, but I wrote it and ran it beyond the time range. I can't find out what the problem is. There should be a problem when reversing the linked list. I will continue to align and improve it in the future.
The idea is:
1. Create a new node temph to store the original header node pointer;
2. Create a new node tempt, which is used to preserve the intermediate node when reversing the linked list;
3. Reverse the linked list to get a new linked list with tail as the head node;
4. Move the head backward one by one and the tail forward one by one. Compare the two pairs. If they are equal, continue to compare; If not, false is returned.
The code is as follows:

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public boolean isPalindrome(ListNode head) {//Double pointer ListNode tail=head; //Traverse from the beginning to find the tail node ListNode tempt=head;//Used to save the intermediate node when reversing the linked list ListNode temph=head;//Keep the direction of the header node while(temph!=null){//Reverse linked list, there is a problem with this code! Caught in a loop tempt=tail; //The temporary tail pointer retains the tail pointer that occurred after the last reversal tail=temph.next;//The real tail pointer moves back one bit tail.next=tempt;//The next node of the tail pointer points to the remaining node temph=temph.next;//The temporary header pointer traverses one bit backward } while(head!=tail){ if(head.val!=tail.val){ return false; } head=head.next; tail=tail.next; } return true; } }

Method 1: copy the value into the array and use the double finger needle method

This is method 1 on the official website. The idea is:
Due to the particularity of the linked list compared with the array, the linked list cannot directly query a value, but needs to be traversed, and can not be searched in reverse order. It can only be searched in one direction, while the array can obtain a value in O(1). Therefore, it is comprehensively considered to use the array list to save the values in the original linked list, and then use double pointers in the array list to move closer one by one at the same time, Compare the values in the array one by one;

be careful:
Due to my lack of attention to the use details of array lists in my daily use, I need to pay attention to the following differences:
1. The creation of array list does not need to have a definite length like array. You can directly list < integer > arrlist = new ArrayList < integer > (); When creating polymorphism, be careful not to lose the second generic;
2. The value obtained from the array list is: arrList.get(i), instead of linkList.val in the usual linked list;
3. The way to get the array length is arrList.size(), instead of arr.length in ordinary arrays.

Execution result: passed
Execution time: 8 ms at all   Java   Beat 40.24% of users in submission
Memory consumption: 50.9 MB in all   Java   Beat 28.78% of users in submission
Pass test case: 85  /  eighty-five

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public boolean isPalindrome(ListNode head) { //Copy the value into the array and use the two finger needle method List<Integer> arrList=new ArrayList<Integer>(); ListNode currentNode=head; while(currentNode!=null){ //Pay attention to the current node. Do not habitually use the next node to judge arrList.add(currentNode.val); currentNode=currentNode.next; } int left=0; int right=arrList.size()-1; while(left<right){ if(!arrList.get(left).equals(arrList.get(right))){//Note the method of obtaining values from array list, which is different from. val return false; } left++; right--; } return true; } }

Method 2: recursion
This is method 2 in the official website. The cleverness and general idea of using recursion are as follows:
When the recursion starts to jump out of the recursion after the last step, it is just like the result of the reversal of the linked list. It is very elegant to compare the beginning and end gradually closer to the middle here! We also define a global variable pointing to the head node outside the method, which is used to compare with the recursive jump out value in the recursive method. In essence, it is performing forward and reverse iterative matching.
Detailed ideas:
1. In the recursive method, first empty the node. If it is empty, it means that it has reached the end of the linked list and returns directly; If it is not empty, it means that the end of the linked list has not been reached, and you still need to continue recursion until the end of the linked list is found;
2. After finding the end, return true and start to jump out of recursion. At this time, directly execute the second if (because recursion starts from this, it also starts to jump out of recursion). if(!true) means that the conditions are not met, directly start to judge the value. If the values are always equal (the recursion will jump out when they are equal) until all recursions jump out, and finally return true, Is palindrome;
3. If two values are not equal when the third if judges whether the values are equal, false is returned here. After that recursion, the second if(!false) satisfies the loop, and all subsequent recursions meet the conditions here. Finally, false is returned, that is, it is not a palindrome.

Execution result: passed
Execution time: 16 ms at all   Java   Defeated 7.92% of users in submission
Memory consumption: 55.4 MB in all   Java   Defeated 12.42% of users in submission
Pass test case: 85  /  eighty-five

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { private ListNode front; //External global variable, because it is compared with the value returned after recursion public boolean isPalindrome(ListNode head) { //Question giving method front=head; return recursivelyCheck(head); //Call the recursive method, pass in the header pointer and return the final value } public boolean recursivelyCheck(ListNode current){ if(current!=null){ //The current node is not empty //If it is passed to the next node, first judge whether it is empty, //If it is empty, it means that it has been recursive to the end of the linked list. It returns true -- > if (! True) - > do not execute, and go to the next if //If it is not empty, continue to call recursively until the last node -- > is found to go to the previous comment if(!recursivelyCheck(current.next)){ //This recursion also jumps out of recursion. If it is false (next comment) when it jumps out, this if is satisfied, and then it is satisfied here, that is, the recursion finally returns false, not a palindrome return false; } //Judge whether the values are equal. If not, return false, step out of recursion, and finally return false if(front.val!=current.val){ return false; } front=front.next; } return true; } }

Method 3: speed pointer
This is method 3 on the official website:
1. Divide the linked list equally: this method uses the slow pointer to walk one node at a time and the fast pointer to walk two nodes at a time. When the next or next point of the fast pointer is null, it indicates that the linked list has been traversed. At this time, the fast pointer has traversed to the end, and the slow pointer is just in the center of the linked list;
2. Reverse and compare: after reversing the second half of the linked list, traverse from front to back from the two linked lists at the same time, compare them one by one, and finally return the obtained results;
3. Restore linked list: generally, the person proposing the comparison does not want his linked list structure to be affected, so he needs to reverse the linked list after the comparison. He only needs to transfer the corresponding segment head node into the method of reversing the linked list again.

Execution result: passed
Execution time: 6 ms at all   Java   Defeated 60.32% of users in submission
Memory consumption: 48.2 MB in all   Java   Beat 82.32% of users in submission
Pass test case: 85  /  eighty-five

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public boolean isPalindrome(ListNode head) {//Speed pointer if(head==null){ return true; } //Find the tail node of the first half ListNode firstHalfEnd = endOfFirstHalf(head); //Get the inverted linked list of the second half segment, and start the inversion from the next node of the last node of the first half segment ListNode secondHalfStart = reverseList(firstHalfEnd.next); //Determine whether it is palindrome ListNode p1 = head; ListNode p2 = secondHalfStart; boolean result = true; while (result && p2 != null) { if (p1.val != p2.val) { result = false; } p1 = p1.next; p2 = p2.next; } //Restore linked list and return results firstHalfEnd.next=reverseList(secondHalfStart);//The second half of the linked list is reversed by this method return result; } private ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } //Realize the fast and slow pointer, and finally return the slow pointer to get the last node of the first half private ListNode endOfFirstHalf(ListNode head) { ListNode fast = head; ListNode slow = head; while (fast.next != null && fast.next.next != null) {//Because fast takes two steps at a time, it needs to judge more fast = fast.next.next; slow = slow.next; } return slow; } }

Pingpingwuqi Xiaobai program yuan is one. You are welcome to exchange advice. If there is anything wrong, you are welcome to leave a message to correct it. Thank you!!!

8 July 2021, 18:03 | Views: 11

Add new comment

For adding a comment, please log in
or create account

0 comments