class ListNode(object):
def __init__(self,x=None):
self.val = x
self.next = None
def List2Node(array):
head = ListNode()#创建头结点
p = head #创建头指针
for i in range(0, len(array)):
if not head.val:
head.val = array[i]
else:
p.next = ListNode(array[i])
p = p.next
return head#返回头结点
if __name__ == "__main__":
array = [1, 2, 3, 4, 5]
link = List2Node(array)
请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。
题目数据保证需要删除的节点 不是末尾节点
lass Solution(object):
def deleteNode(self, node):
node.val = node.next.val
node.next = node.next.next
如果有多个,仅删除最前面的指定值
```python
class Solution(object):
def deleteNode(self, head, val):
if head.val == val:
return head.next
pre,p = head, head.next
while p and p.val!=val:
pre = p
p = pre.next
if p:
pre.next = p.next
return head
#### 删除所有指定值
![在这里插入图片描述](https://img-blog.csdnimg.cn/2660a9ea9b124956ab6be76bc0bf00aa.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAOTMzNzEx,size_20,color_FFFFFF,t_70,g_se,x_16)
注意:[7777]这样的
- 方法一:头结点处分情况考虑
```python
class Solution(object):
def removeElements(self, head, val):
# 头结点可能等于val
if head == None:
return head
while head!= None and head.val == val:
head = head.next
if head==None:
return head
pre = head
while pre.next:
if pre.next.val == val:
pre.next = pre.next.next
else:
pre = pre.next
return head
class Solution(object):
def removeElements(self, head, val):
dummy = ListNode(val-1)
dummy.next = head
pre = dummy
while pre.next:
if pre.next.val == val:
pre.next = pre.next.next
else:
pre = pre.next
return dummy.next
class Solution(object):
def deleteMiddle(self, head):
if head.next is None:
return None
# 链表从两个元素起
slow, fast, pre = head, head, None
# 保证fast.next不为空
while fast and fast.next:
fast = fast.next.next
pre = slow
slow = slow.next
pre.next = slow.next
return head
给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
class Solution(object):
def deleteDuplicates(self, head):
if not head or not head.next:
return head
pre,p = head,head.next
while p:
if pre.val == p.val:
pre.next = p.next
else:
pre = p
p = p.next
return head
注意:只留下没有重复的数字,例如
输入:head = [1,1,1,2,3]
输出:[2,3]
比如: 1 -> 2 -> 2 -> 2 -> 3,我们用一个 pre 指向 1;当 cur 指向第一个 2 的时候,发现 cur.val == cur.next.val ,所以出现了值重复的节点啊,所以 cur 一直后移到最后一个 2 的时候,发现 cur.val != cur.next.val ,此时 cur.next = 3 ,所以 pre.next = cur.next ,即让1 的 next 节点是 3,就把中间的所有 2 都删除了。
class Solution(object):
def deleteDuplicates(self, head):
if not head or not head.next:
return head
dummy = ListNode(0)
dummy.next = head
pre, cur = dummy, head
while cur:
while cur.next and cur.val == cur.next.val:
cur = cur.next
if pre.next == cur:
# pre和cur之间没有重复节点,pre后移
pre = pre.next
else:
pre.next = cur.next
cur = cur.next
return dummy.next
class Solution(object):
def removeNthFromEnd(self, head, n):
if head==None:
return None
def length(head):
n = 0
while head:
n+=1
head = head.next
return n
length = length(head)
dummy = ListNode(-1)
dummy.next = head
pre= dummy
# 遍历到前一个节点
for i in range(length-n):
pre = pre.next
pre.next = pre.next.next
return dummy.next
即不能先算出长度,再找点
class Solution(object):
def removeNthFromEnd(self, head, n):
if head==None:
return None
dummy = ListNode(-1)
dummy.next = head
p, q = dummy,head
for i in range(n):
q = q.next
while q:
p = p.next
q = q.next
p.next = p.next.next
return dummy.next
class ListNode(object):
def __init__(self,x):
self.val = x
self.next = None
class Solution(object):
def reversePrint(self, head):
queue = []
temp = head
while temp !=None:
queue.append(temp)
temp = temp.next
res= []
for i in range(len(queue)):
res.append(queue.pop().val)
return res
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
class Solution(object):
def reverseList(self, head):
# 链表转数组
def get_list(head):
res = []
p = head
while p:
res.append(p.val)
p = p.next
return res
# 数组转链表
def list_to_node(res):
if len(res)==0:
return None
head = ListNode(res[0])
p = head
for i in range(1,len(res)):
p.next = ListNode(res[i])
p = p.next
return head
res = get_list(head)
res = list(reversed(res))
return list_to_node(res)
class Solution:
def reverseList(self, head):
p, rev = head, None
while p:
rev, rev.next, p = p, rev, p.next
return rev
public static ListNode reverseListIterative(ListNode head) {
ListNode prev = null; //前指针节点
ListNode curr = head; //当前指针节点
//每次循环,都将当前节点指向它前面的节点,然后当前节点和前节点后移
while (curr != null) {
ListNode nextTemp = curr.next; //临时节点,暂存当前节点的下一节点,用于后移
curr.next = prev; //将当前节点指向它前面的节点
prev = curr; //前指针后移
curr = nextTemp; //当前指针后移
}
return prev;
}
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
res[left-1:right] = reversed(res[left-1:right])
class Solution(object):
def reverseBetween(self, head, left, right):
# 将链表转为列表
def node2list(head):
res = []
while head:
res.append(head.val)
head = head.next
return res
# 列表生成链表
def list2node(res):
if len(res)==0:
return None
head = ListNode(res[0])
p = head
for i in range(1,len(res)):
p.next = ListNode(res[i])
p = p.next
return head
res = node2list(head)
#列表部分反转
res[left-1:right] = reversed(res[left-1:right])
return list2node(res)
举例
Input: head = [1,2,3,4,5], left = 2, right = 4
Output: [1,4,3,2,5]
将234部分反转为432
我们需要找到2前面的节点1,也就是这里的begin,然后pre=none,q=2开始,反转链表,结束后。q在5这个节点,pre在4这个点,我们需要把2指向5,然后把1指向4,这时候begin.next其实就是这里的2,所以begin.next.next = q,begin.next = pre
class Solution(object):
def reverseBetween(self, head, left, right):
dummy = ListNode(-100)
dummy.next = head
begin = dummy
# 遍历到left前一个节点
for i in range(left-1):
begin = begin.next
cur = begin.next
pre = None
# 180度反转
for i in range(left,right+1):
next_ = cur.next
cur.next = pre
pre = cur
cur = next_
# 两个边界处理,注意这两行位置不能换
begin.next.next = cur
begin.next = pre
return dummy.next
把链表收尾相接变成环形,计算出链表长度n,k=1时,第n- 1个为head,第n-2个为尾巴,k时,n-(k % n)是新链表头节点的索引,n-(k % n)-1 为尾巴
找到尾巴处,新建dummy哑结点,哑结点指向新头结点,即尾巴下一个节点,再令尾巴指向none,返回dummy.next
注意:k可能大于n,这时仅需用k%n代替k即可
class Solution(object):
def rotateRight(self, head, k):
if head==None or head.next == None or k==0:
return head
n = 1
cur = head
# 移到最后一个节点处
while cur.next:
cur = cur.next
n += 1
cur.next = head
# 尾巴:n-k%n-1,哑结点指向尾巴下一个,尾巴指向None
for i in range(n-k%n-1):
head = head.next
dummy = ListNode(-1)
dummy.next = head.next
head.next = None
return dummy.next
Input: head = [1,2,3,4]
Output: [2,1,4,3]
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode temp = dummy;
while(temp.next!=null&& temp.next.next!=null){
ListNode pre = temp.next;
ListNode p = temp.next.next;
temp.next = p;
pre.next = p.next;
p.next = pre;
temp = pre;
}
return dummy.next;
}
}
class Solution {
public ListNode swapPairs(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode newHead = head.next;
head.next = swapPairs(newHead.next);
newHead.next = head;
return newHead;
}
}
假设链表 A 的头节点到相交点的距离是 a,链表 B 的头节点到相交点的距离是 b,相交点到链表终点的距离为 c。我们使用两个指针,分别指向两个链表的头节点,并以相同的速度前进,若到达链表结尾,则移动到另一条链表的头节点继续前进。按照这种前进方法,两个指针会在a + b + c 次前进后同时到达相交节点。注意:另一个头结点
比如说:A=[1,2,3,4,5] B=[6,7,4,5],相交节点是4。A到相交节点距离为a=3,B到相交节点距离为b=2,c=2。所以B先走完b+c步,然后B开始从A处走,得走a步到交点,而A走完a+c步后转到B走,再走b步到交点,他们刚好都走了a+b+c步
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 ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
}
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。PS,回文数组:前后对称
可以直接b=list(reversed(a))
也可以利用stack栈来实现逆序,利用栈先进后出的性质
也可以利用对称,考察前后两半
if len(tempNum)>0:
while i<len(tempNum)/2: #对称的特点
if tempNum[i]!=tempNum[len(tempNum)-1-i]:
print('不是回文')
break
i=i+1 #循环变量自增,差点忘记写
if i>=len(tempNum)/2:
print(tempNum, '是回文')
直接reversed
class Solution(object):
def isPalindrome(self, head):
def node2list(head):
res = []
while head:
res.append(head.val)
head = head.next
return res
res = node2list(head)
res_re = list(reversed(res))
return res == res_re
先使用快慢指针找到链表中点,再把链表切成两半;然后把后半段翻转;最后比较两半是否相等。
方法一:数组+字符串
数组转为字符串:str = ''.join(str(x) for x in A)
方法二:链表对应相加
class Solution(object):
def addTwoNumbers(self, l1, l2):
dummy = ListNode(-1)
cur = dummy
carry = 0
# carry为满进值
while l1 or l2:
# 链长较短就补0
x = l1.val if l1!=None else 0
y = l2.val if l2!=None else 0
sum_ = x+y+carry
carry = sum_/10
sum_ = sum_%10
cur.next = ListNode(sum_)
cur = cur.next
l1 = l1.next if l1!=None else None
l2 = l2.next if l2!=None else None
if carry == 1:
cur.next = ListNode(carry)
return dummy.next
class Solution(object):
def addTwoNumbers(self, l1, l2):
s1, s2 = [], []
while l1:
s1.append(l1.val)
l1 = l1.next
while l2:
s2.append(l2.val)
l2 = l2.next
carry = 0
ans = None
# 注意要加上carry!=0,最后可能需要进位
while s1 or s2 or carry!=0:
a = s1.pop() if s1 else 0
b = s2.pop() if s2 else 0
sum_ = a+b+carry
carry = sum_/10
sum_ = sum_%10
curnode = ListNode(sum_)
curnode.next = ans
ans = curnode
return ans
class Solution(object):
def swapPairs(self, head):
if head == None:
return None
dummy = ListNode(-100)
dummy.next = head
pre, p, next_ = dummy, head, head.next
while next_:
temp = next_.next
next_.next = p
p.next = temp
pre.next = next_
pre = p
p = p.next
next_ = temp.next if temp!= None else None
return dummy.next
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode next = head.next;
head.next = swapPairs(next.next);
next.next = head;
return next;
}
}
class Solution(object):
def partition(self, head, x):
if head==None or head.next==None:
return head
small = ListNode(-1)
large = ListNode(-1)
smallHead = small
largeHead = large
# 构造两个链表
while head:
if head.val < x:
small.next = head
small = small.next
else:
large.next = head
large = large.next
head = head.next
large.next = None
small.next = largeHead.next
return smallHead.next
给定两个增序的链表,试将其合并成一个增序的链表。
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
prehead = ListNode(-1)
prev = prehead
while l1 and l2:
if l1.val <= l2.val:
prev.next = l1
l1 = l1.next
else:
prev.next = l2
l2 = l2.next
prev = prev.next
# 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 if l1 is not None else l2
return prehead.next
java版本
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);
ListNode prev = prehead;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
prev.next = l1;
l1 = l1.next;
} else {
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
}
给定单链表的头节点 head ,将下标为奇数的放在一起,偶数的放在一起,顺序不变,默认第一个数为奇数。要求时间复杂度O(1),空间复杂度O(N)
新生成一个链表和一个队列存储偶数的元素,然后奇数遍历结束,就把偶数加进去。
public ListNode oddEvenList(ListNode head) {
ListNode dummy = new ListNode(-1);
ListNode p = head, temp = dummy;
int count = 0;
Deque ll = new ArrayDeque<Integer>();
while(p!=null){
count ++;
if(count%2==1){
temp.next = new ListNode(p.val);
temp = temp.next;
}else ll.add(p.val);
p = p.next;
}
while(!ll.isEmpty()){
Integer a = (Integer)ll.pollFirst();
temp.next = new ListNode(a.intValue());
temp = temp.next;
}
return dummy.next;
}
但是这样做太复杂了,有没有更简单的呢?
分别建立两个链表,一个奇数链一个偶数链,然后连一起
举例说明:2-1-3-5-6-4-7
奇头odd 指向2,偶头even 指向1,然后odd 指向even后一个即3,odd移动到3,这时候偶even 再指向奇的后一个即5,偶移动到5,以此类推。最后odd在指向偶的第一个evenhead。
class Solution {
public ListNode oddEvenList(ListNode head) {
if (head == null) {
return head;
}
ListNode evenHead = head.next;
ListNode odd = head, even = evenHead;
while (even != null && even.next != null) {
odd.next = even.next;
odd = odd.next;
even.next = odd.next;
even = even.next;
}
odd.next = evenHead;
return head;
}
}
Input: head = [4,2,1,3]
Output: [1,2,3,4]
要求递增,时间复杂度O(n logn) ,空间复杂度O(1)
但是这个超出内存限制,因此我们不能新建一个优先队列
public ListNode sortList(ListNode head) {
// 1、递归结束条件
if (head == null || head.next == null) {
return head;
}
// 2、找到链表中间节点并断开链表 & 递归下探
ListNode midNode = middleNode(head);
ListNode rightHead = midNode.next;
midNode.next = null;
ListNode left = sortList(head);
ListNode right = sortList(rightHead);
// 3、当前层业务操作(合并有序链表)
return mergeTwoLists(left, right);
}
找中点
// 找到链表中间节点(876. 链表的中间结点)
private ListNode middleNode(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head.next.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
合并两个有序链表
// 合并两个有序链表(21. 合并两个有序链表)
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode sentry = new ListNode(-1);
ListNode curr = sentry;
while(l1 != null && l2 != null) {
if(l1.val < l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
curr.next = l1 != null ? l1 : l2;
return sentry.next;
}