160.Intersection of Two Linked Lists
注意,链表结点相同意味着他们的值相同,下一个结点也相同
方法1:暴力法
方法2:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null)
return null;
ListNode pa=headA,pb=headB;
while(pa!=pb)
{
pa=pa==null?headA:pa.next;
pb=pb==null?headB:pb.next;
}
return pa;
}
}
方法3哈希法:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> set=new HashSet();
while (headA!=null){
set.add(headA);
headA=headA.next;
}
while (headB!=null){
if(set.contains(headB))
return headB;
headB=headB.next;
}
return null;
}
}
206 Reverse Linked List
头插法:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode newHead = null;
while (head != null) {
ListNode next = head.next;
head.next = newHead;//画图理解
newHead = head;
head = next;
}
return newHead;
}
}
递归解法:
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode next = head.next;
ListNode newHead = reverseList(next);
next.next = head;
head.next = null;
return newHead;
}
21. 合并两个有序链表
递归解法:
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}
83. 删除排序链表中的重复元素
递归解法:
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null||head.next==null)
return head;
head.next=deleteDuplicates(head.next);
return head.val==head.next.val?head.next:head;
}
}
19. 删除链表的倒数第N个节点
①解法1:两次遍历,统计链表的长度
②快慢指针
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode first = dummy;
ListNode second = dummy;
// Advances first pointer so that the gap between first and second is n nodes apart
for (int i = 1; i <= n + 1; i++) {
first = first.next;
}
// Move first to the end, maintaining the gap
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
24. 两两交换链表中的节点
①解法一 递归:
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null||head.next==null)
/*先判断head在判断next*/
return head;
ListNode next= head.next;
head.next=swapPairs(head.next.next);
next.next=head;
return next;
}
}
②解法二迭代:
public ListNode swapPairs(ListNode head) {
ListNode node = new ListNode(-1);
node.next = head;
ListNode pre = node;
while (pre.next != null && pre.next.next != null) {
ListNode l1 = pre.next, l2 = pre.next.next;
ListNode next = l2.next;
l1.next = next;
l2.next = l1;
pre.next = l2;
pre = l1;
}
return node.next;
}
445. 两数相加 II
逆序处理:用栈,carray表示进位
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> l1Stack = buildStack(l1);
Stack<Integer> l2Stack = buildStack(l2);
ListNode head = new ListNode(-1);
int carry = 0;
while (!l1Stack.isEmpty() || !l2Stack.isEmpty() || carry != 0) {
int x = l1Stack.isEmpty() ? 0 : l1Stack.pop();
int y = l2Stack.isEmpty() ? 0 : l2Stack.pop();
int sum = x + y + carry;
ListNode node = new ListNode(sum % 10);
node.next = head.next;
head.next = node;
carry = sum / 10;
}
return head.next;
}
private Stack<Integer> buildStack(ListNode l) {
Stack<Integer> stack = new Stack<>();
while (l != null) {
stack.push(l.val);
l = l.next;
}
return stack;
}
}
2. 两数相加
这里直接遍历就可,做法也是一样,t表示进位
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(-1), pre = dummyHead;
int t = 0;
while (l1 != null || l2 != null || t != 0) {
if (l1 != null) {
t += l1.val;
l1 = l1.next;
}
if (l2 != null) {
t += l2.val;
l2 = l2.next;
}
pre.next = new ListNode(t % 10);
pre = pre.next;
t /= 10;
}
return dummyHead.next;
}
}
234. 回文链表
快慢指针,逆转链表
class Solution {
public:
//题解:快慢指针法,快指针走两步,慢指针走一步,找到链表的中点。然后,翻转后半部分。最后从头、中点开始判断是否相同。
bool isPalindrome(ListNode* head) {
if(!head||!head->next)return true;
ListNode *fast=head,*slow=head,*pre=nullptr;
//1、找到链表的中点,链表长度奇偶不影响
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
}
//2、将slow之后链表进行断开且反转,最后翻转完成之后pre指向反转链表的头节点
while(slow){
ListNode *p=slow->next;
slow->next=pre;
pre=slow;
slow=p;
}
//3、前后链表进行比较,注意若为奇数链表,后半部分回比前部分多1一个节点,然而我们只比较相同长度的节点值,巧妙地避开这点判断
while(head&&pre){
if(head->val!=pre->val)return false;
head=head->next;
pre=pre->next;
}
return true;
}
};
725. 分隔链表
注意一个地方:
ListNode temm=temp; 比如这里,temm和temp属于同一个结点,如果把temm的next设置为空,那么temp的next也为空
题目描述:把链表分隔成 k 部分,每部分的长度都应该尽可能相同,排在前面的长度应该大于等于后面的。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode[] splitListToParts(ListNode root, int k) {
ListNode p=root;
ListNode[] listArrary=new ListNode[k];
int listLength=0,avgLength=0,leftLength=0;
while(p!=null){
p=p.next;
listLength++;
}
avgLength=listLength/k; //*每一个数组元素的长度*/
leftLength=listLength%k; //*剩余的长度 */
if(listLength<=k){
ListNode temp=root;
for(int i=0;i<k;i++){
if(temp!=null){
listArrary[i]=temp; // 注意 listArrary[i]=temp; 那么这两个就是同一个结点
ListNode temm=temp.next; //这里一定要暂存temp.next的结点;
listArrary[i].next=null;
temp=temm;
}
else
listArrary[i]=null;
}
return listArrary;
}
for(int i=0;i<k;i++){
listArrary[i]=root;
for(int j=0;j<avgLength-1;j++){
root=root.next;
}
ListNode temp=null;
if(leftLength!=0){ //看看是否还有剩余长度
root=root.next;
temp=root.next;
root.next=null;
leftLength--;
}
else
{
temp=root.next;
root.next=null;
}
root=temp;
}
return listArrary;
}
}
328. 奇偶链表
画图快速理解
class Solution {
public ListNode oddEvenList(ListNode head) {
if(head==null)
return head;
ListNode first=head,two=head.next,third=two;
//分别指向奇结点和偶节点,third用来连接成功后的奇偶链表
while(two!=null&&two.next!=null){
//two不为空,first必不为空,first为不空,two可能为空
//two指针一定在first后面,所以判断two就可以了
first.next=first.next.next;
first=first.next;
two.next=two.next.next;
two=two.next;
}
first.next=third;
return head; //返回头指针
}
}