Leetcode刷题(21) 链表反转系列,数组的旋转
206. 反转链表
集体方法参考labuladong的递归反转链表的一部分,文本是用python的实现
方法一:递归反转整个链表
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# base case
if head == None:
return None
# base case
if head.next == None:
return head
last = self.reverseList(head.next)
# reverse
head.next.next = head
# 被反转的node的next先指向null
head.next = None
return last
方法二:迭代反转整个链表
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head == None:
return None
cur = head
nxt = head
pre = None
while(cur!=None):
# 记录下一个要反转的node
nxt = cur.next
# 反转当前的node
cur.next = pre
# 更新pre and cur用于下次的反转
pre = cur
cur = nxt
return pre
92. 反转链表 II
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def __init__(self):
self.suc = None
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
# 反转前n个节点
def reverseN(head, n):
if n == 1:
self.suc = head.next
return head
last = reverseN(head.next, n - 1)
head.next.next = head
head.next = self.suc
return last
# base case
if m == 1:
return reverseN(head, n)
# 不断递归直到触发了basecase m == 1
head.next = self.reverseBetween(head.next, m-1, n-1)
return head
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseBetween(self, head, m, n):
"""
:type head: ListNode
:type m: int
:type n: int
:rtype: ListNode
"""
def reverse(a, b):
pre = b
cur = a
while(cur != b):
nxt = cur.next
cur.next = pre
pre = cur
cur =nxt
return pre
if m == 1:
b = head
for i in range(n):
b = b.next
return reverse(head, b)
else:
head.next = self.reverseBetween(head.next, m - 1, n - 1)
return head
具体方法参考labuladong的如何k个一组反转链表,文本是用python的实现
25. K 个一组翻转链表
reverse(a, b)使用的是迭代的方法,在开区间[a, b)中反转链表,reverseKGroup(a, k)使用的是递归的方法。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
def reverse(a, b):
pre = None
cur = a
nxt = a
while(cur != b):
# 记录下当前要翻转节点的next
nxt = cur.next
# 翻转当前节点
cur.next = pre
# update cur and pre
pre = cur
cur = nxt
return pre
if head == None:
return None
a = head
b = head
for i in range(0, k):
# 剩下的node不满足k个直接返回当前的head不做反转
if b == None:
return head
b = b.next
newHead = reverse(a, b)
# a作为组中新的最后一个节点, next指向后继, 也就是下一组的newHead
a.next = self.reverseKGroup(b, k)
# head.next = self.reverseKGroup(b, k)
return newHead
189. 旋转数组
这题是数组的旋转, 不好放哪我就放在这个部分了
暴力法:一次一次的原地旋转,旋转k次
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
# 一次一次旋转, 旋转k次
for i in range(k):
# pre是用来记录将要用于去替换下一个位置的元素的元素
pre = nums[n - 1]
for j in range(n):
tmp = nums[j]
nums[j] = pre
pre = tmp
新建一个数组来辅助,一次性定位到每个元素的指定位置
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
# 一次一次旋转, 旋转k次
for i in range(k):
# pre是用来记录将要用于去替换下一个位置的元素的元素
pre = nums[n - 1]
for j in range(n):
tmp = nums[j]
nums[j] = pre
pre = tmp
华为机试2020.08.26 的第一题题解, 有点像上一题:
import sys
def main():
sys.stdin = open('input.txt', 'r')
lines = sys.stdin.readlines()
n = len(lines)
index = 0
while index < n:
line = list(map(int, lines[index].strip().split()))
nums = []
for num in line:
num = list(bin(num)[2:].zfill(32))
i = 0
while i < 32:
tmp = num[i]
num[i] = num[i + 1]
num[i + 1] = tmp
i += 2
nums.append(num)
_1 = '0'
_2 = '0'
for i, num in enumerate(nums):
if i == 0:
num.insert(0, '0')
num.insert(0, '0')
_1 = num.pop()
_2 = num.pop()
nums[i] = num
else:
num.insert(0, _1)
num.insert(0, _2)
_1 = num.pop()
_2 = num.pop()
nums[i] = num
# 最后处理第一个数
nums[0][0] = _2
nums[0][1] = _1
l = len(nums)
for i, num in enumerate(nums):
if i < l - 1:
print(int(''.join(num), base=2), end=" ")
else:
print(int(''.join(num), base=2))
index += 1
if __name__ == "__main__":
main()
234. 回文链表
递归判断
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def __init__(self):
self.left = None
def isPalindrome(self, head):
self.left = head
"""
:type head: ListNode
:rtype: bool
"""
def isp(head):
if head == None:
return True
res = isp(head.next)
res = res and head.val == self.left.val
self.left = self.left.next
return res
return isp(head)
用快慢指针找到中点,然后从中点开始反转链表,再逐个进行比较
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
def reverse(root):
cur = root
pre = None
while(cur!=None):
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
def findMid():
slow = head
fast = head
while (fast!=None and fast.next!=None):
slow = slow.next
fast = fast.next.next
if fast != None:
slow = slow.next
return slow
left = head
mid = findMid()
right = reverse(mid)
while right!=None:
if left.val != right.val:
return False
left = left.next
right = right.next
return True
189. 旋转数组
撑杆跳法
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
n = len(nums)
k = k % n
count = 0
start = 0
# count是用来控制循环的
while count < n:
current = start
prev = nums[start]
# 使用flag的原因是为了让第一次循环可以进行
flag = 0
while start != current or flag == 0:
flag = 1
nxt = (current + k) % n
temp = nums[nxt]
# 撑杆跳
nums[nxt] = prev
# 更新prev和current
prev = temp
current = nxt
# 记录已经移动了几个元素
count += 1
# start移动到下一位
start += 1