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。
知识越抽象复杂,产生疯癫的危险性就越大。 —— 哲学家,米歇尔 福柯
相关文章推荐
- LeetCode基本记录【4】// BASIC NOTES AND CODES OF LEETCODE [ 4 ]
- Study notes "Basic algorithms of dynamic programming and backtracking
- Java for LeetCode 201 Bitwise AND of Numbers Range
- [LeetCode]104. Basic Calculator II基本计算器
- Leetcode-201- Bitwise AND of Numbers Range
- The History of Notes and Domino
- 基本图论定义与术语(Basic Definition and Glossary in Graph The)
- leetcode 201: Bitwise AND of Numbers Range
- 个人记录-LeetCode 17. Letter Combinations of a Phone Number
- MM--A List of Tables and Tcodes about MM
- NOTES of NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE
- LeetCode--Bitwise AND of Numbers Range
- Leetcode Bitwise AND of Numbers Range
- [LeetCode 201] Bitwise AND of Numbers Range
- Bitwise AND of Numbers Range——LeetCode
- [LeetCode] Bitwise AND of Numbers Range 数字范围位相与
- leetcode之Bitwise AND of Numbers Range
- leetCode191/201/202/136 -Number of 1 Bits/Bitwise AND of Numbers Range/Happy Number/Single Number
- [Leetcode] Bitwise And of numbers range
- [LeetCode] Bitwise AND of Numbers Range