您的位置:首页 > 其它

LeetCode基本记录【2】// BASIC NOTES AND CODES OF LEETCODE [ 2 ]

2018-03-20 22:55 459 查看

LeetCode基本记录【2】

19. Remove Nth Node From End of List

Given a linked list, remove the nth node from the end of list and return its head.

For example,

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:

Given n will always be valid.

Try to do this in one pass.

# 题目中要求一趟过 one pass,所以不允许先查出list的长度,再用from beginning的remove方法。这里维护一个距离为n的指针,使得第一个指向null时
# 第二个刚好指向倒数第n个
# 注意设置一个dummy结点用来处理特殊情况。e.g. 删除长度为n的list的倒数第n个,也就是头一个元素
# dummy结点在处理linked list问题中经常使用,目的就是处理特殊情况,并且保持不变。需要注意。
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode
:type n: int
:rtype: ListNode
"""
dum = ListNode(0)
dum.next = head
fr = sc = dum
for i in range(n+1):
fr = fr.next
while not fr == None:
fr = fr.next
sc = sc.next
sc.next = sc.next.next
return dum.next


22. Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

For example, given n = 3, a solution set is:

[

“((()))”,

“(()())”,

“(())()”,

“()(())”,

“()()()”

]

此题的一个backtrack的解题思路,有大神归纳为下面这个准则。实际上,backtracking是递归实现,但是在这个题目中相当于是对于不合适的值不返回,也就是把违反规则的树枝全部切掉(因为不返回,所以不但子树的树根没有,而且下面的节点也没有了,所以只在符合条件的情况下有效)。

if (左右括号都已用完) {
加入解集,返回
}
否则开始试各种选择
if (还有左括号可以用) {
加一个左括号,继续递归
}
if (右括号小于左括号) {
加一个右括号,继续递归
}


# 根据上面的思路写代码如下:
# 这个用法还是比较难理解的,需要反复练习
class Solution(object):
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
"""
ls = []
def backtracker(s, l, r, lis):
if l :
backtracker(s+'(', l-1, r, lis)
if r > l :
backtracker(s+')', l, r-1, lis)
if not r :
lis.append(s)
return lis
return backtracker('', n, n, [])


24. Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head.

For example,

Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

# 题目要求不能修改values,也就是说只能动指针。而且算法需要在常数空间,所以也不能开新数组,只能原位操作,修改指针。
# 只要写好指针的变化关系就不难解决,但是比较繁琐,需要花时间考虑不同情况。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
def swapPairs(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head :
return None
if not head.next :
return head
dummy = ListNode(0)
dummy.next = head
p0, p1, p2 = dummy, dummy.next, dummy.next.next
while p1 and p2 :
t0, t1, t2 = p0.next, p1.next, p2.next
p0.next, p1.next, p2.next = t1, t2, t0
p0 = p1
p1 = p0.next
if p1:
if p1.next:
p2 = p1.next
else:
break
else:
break
return dummy.next


29. Divide Two Integers

Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT.

# 试图自己写,总是TLE,要不就是结果不对,放弃。。。
# 下面直接贴上一个discuss里的标答,日后研究。
class Solution:
# @return an integer
def divide(self, dividend, divisor):
positive = (dividend < 0) is (divisor < 0)
dividend, divisor = abs(dividend), abs(divisor)
res = 0
while dividend >= divisor:
temp, i = divisor, 1
while dividend >= temp:
dividend -= temp
res += i
i <<= 1
temp <<= 1
if not positive:
res = -res
return min(max(-2147483648, res), 2147483647)


31. Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3 → 1,3,2

3,2,1 → 1,2,3

1,1,5 → 1,5,1

# 显然地,如果序列为descending order,那么已经是最大的了,不存在一个排序使得它更大,按照题意,直接变回ascending order,不需要排序,直接reverse
# 如果不是这样,那么从后往前找一个连续的子序列,如果descend就继续向前,直到找到一个前项小于后项的,记做a[i-1],a[i]
# 那么可以对这个数进行一个调整,由于要求是next permutation,所以前面的高位不能动,只改变a[i-1]
# 所以需要在a[i-1]后面找到用来替换的,即just大于a[i-1]的数值,也就是大于它的里面的最小的那一个
# 由于后面都是descending order,所以只要找到第一个小鱼被替换的,它的前一个就是用来替换的。
# 换完以后并不影响后面的顺序,因此需要把后面的descending变成ascending,直接Reverse
# 注意python中list变量的一段进行Reverse的方法。。。。
# 另外,nums[i-1] >= nums[i] 就要左移。。。知道找到一个严格小于的。。少了等号会产生错误
class Solution(object):
def nextPermutation(self, nums):
"""
:type nums: List[int]
:rtype: void Do not return anything, modify nums in-place instead.
"""
if len(nums) < 2 : return
i = len(nums) -1
while i-1 >= 0 and nums[i-1] >= nums[i]:
i -= 1
if i-1 == -1 :
nums.reverse()
return
target, tid = nums[i-1], i-1
while i < len(nums) - 1 and nums[i] > target:
i += 1
i = i if nums[i] > target else i-1
nums[tid] = nums[i]
nums[i] = target
nums[tid+1:] = nums[:tid:-1]
return


33. Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

# 虽然rotated但是本质上仍然是一个有序的序列,所以可以直接通过二分查找binary search
# 只是这时候的判断语句与顺序查找的不同,首先看mid落在左半边还是右半边,通过比较mid和两边的大小就可以知道,然后在判断target落在那个区间
# 其余和二分查找相同
class Solution(object):
def search(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if not nums : return -1
if len(nums) == 1 :
return 0 if nums[0] == target else -1
l, r = 0, len(nums) - 1
while l <= r :
mid = (l + r) // 2
if nums[mid] == target:
return mid
if nums[mid] >= nums[l] :
if target < nums[mid] and target >= nums[l] :
r = mid - 1
else :
l = mid + 1
elif nums[mid] <= nums[r] :
if target > nums[mid] and target <= nums[r] :
l = mid + 1
else :
r = mid - 1
return -1


34. Search for a Range

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,

Given [5, 7, 7, 8, 8, 10] and target value 8,

return [3, 4].

# 此题可以有多种解法,但是题目中要求了要用O(logn)的时间,所以明显可知需要用二分查找来做
# 具体的实现方法,如果不考虑时间限制,可以从左到右直接遍历,也可以从两侧遍历来找左右边界
# 如果非要用二分查找,可以有两种方法:一,可以只要查到一个就返回,然后向两边查找,如果个数有限的话,那么勉强算是个logn的方法
# 二,就是利用修改后的binary search 的代码,分别找左右边界,具体的modify方法就是改变while的条件,以前是严格等于才移动二分,而现在
# 对于比如 [1,2,3,4,5,5,5,5,6,8,9] 这样的,如果某个mid为5,那么普通的binary search认为已经找到了,而这里还需要左移去寻找左节点,右移去寻找
# 右节点。代码如下:
# 对于边界的处理还是要仔细。。。。
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
if not nums : return [-1, -1]
if len(nums) == 1:
if nums[0] == target:
return [0, 0]
else :
return [-1, -1]
l1, r1 = 0, len(nums) - 1
l2, r2 = l1, r1
while l1 <= r1 or l2 <= r2:
if l1 == r1 and l2 == r2 :
if nums[l1] == nums[l2] == target: # in case r2 didnt move
return [l1, l2]
if nums[l1] == nums[l2-1] == target:
return [l1, l2 - 1]
else :
break
mid1 = (l1 + r1) // 2
mid2 = (l2 + r2) // 2
if not l1 == r1:
if nums[mid1] >= target:
r1 = mid1
else :
l1 = mid1 + 1
if not l2 == r2:
if nums[mid2] <= target:
l2 = mid2 + 1
else :
r2 = mid2
return [-1, -1]


36. Valid Sudoku

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character ‘.’.

A partially filled sudoku which is valid.

Note:

A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

# 简单但是繁琐。。。
# python中的list没法直接对column进行操作,对于用惯了numpy的array形式的人来说很不友好。。
# 另外,somelist.append(someitem) 不需要返回值,直接添加到list中
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
for nrow in range(9):
row = board[nrow]
if self.hasRepeatedNumber(row) :
return False
for ncol in range(9):
col = []
for i in range(9):
col.append(board[i][ncol])
if self.hasRepeatedNumber(col):
return False
pnt = [(i,j) for i in [0,3,6] for j in [0, 3, 6]]
for tpl in pnt:
patch = self.formPatch(board, tpl)
if self.hasRepeatedNumber(patch):
return False
return True

def formPatch(self, bd, point):
pat = []
for i in range(point[0], point[0] + 3):
for j in range(point[1], point[1] + 3):
pat.append(bd[i][j])
return pat

def hasRepeatedNumber(self, ls):
assert len(ls) == 9
sto = [0 fo
cbda
r i in range(9)]
for i in range(9):
if not ls[i] == '.' :
if sto[int(ls[i])-1] == 0:
sto[int(ls[i])-1] = 1
else:
return True
return False


39. Combination Sum

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

Note:

All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.


For example, given candidate set [2, 3, 6, 7] and target 7,

A solution set is:

[

[7],

[2, 2, 3]

]

# 典型的利用回溯搜索的题型,此处需要多练习掌握技巧
# backtracking实际上是一种深度优先的搜索算法,可以看成是对所有可能结果空间根据要求的constraint将不符合要求的进行剪枝,从而避免了对它下面的
# 所有不合理的子树进行搜索
# backtracking实际上是一定的template的,此处先略。
# 注意如果不满足停止条件且不违反约束的话,就调用以此为root的下面所有的节点的可能情况,递归调用helper,不用return,满足条件在节点会return的
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
res = []
nums = sorted(candidates)
self.helper(candidates, target, 0, [], res)
return res

def helper(self, nums, target, idx, path, res):
if target < 0 :
return
elif target == 0 :
res.append(path)
return
for i in range(idx, len(nums)):
self.helper(nums, target - nums[i], i, path + [nums[i]], res)


40. Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.


For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,

A solution set is:

[

[1, 7],

[1, 2, 5],

[2, 6],

[1, 1, 6]

]

# 这个题的candidates里已经有了duplicates,所以要注意solution不要有重复
# 所以需要在append某次的path时进行一个判断
# 另外,不允许用多次,所以idx相比于前面应当+1s
class Solution(object):
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
res = []
nums = sorted(candidates)
self.helper(nums, target, -1, [], res)
return res

def helper(self, nums, target, idx, path, res):
if target < 0: # violate the constraint, return
return
if target == 0: # reach one leaf node, return
for chek in res:
if chek == path:
return
res.append(path)
return
#        if target > 0: # not violate but also not leaf, make a subtree with it as root
for i in range(idx+1,len(nums)):
self.helper(nums, target - nums[i], i, path + [nums[i]], res)


以上十道题完毕,2018年03月20日22:50:53。

知识越抽象复杂,产生疯癫的危险性就越大。 —— 哲学家,米歇尔 福柯
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: