2020.8.19
- 问:在数组中找到2个数之和等于给定的数字,结果返回这两个数字的索引。
- 思路
最优的做法时间复杂度可以做到O(n)。
顺序扫描数组,对每一个元素,在Dictionary中找能组合给定值的另一个数字,如果找到了,直接返回下标即可。如果找不到,就把这个数字存入Dictionary中,等待扫描到另一个数字的时候,再取值判断返回结果。
- 代码
class Solution{
func twoSum(_ nums:[Int],_ target:Int) -> [Int?] {
var m = Dictionary<Int,Int>()
for i in 0...nums.count-1 {
let another:Int = target - nums[i]
if let anotherKey = m[another] {
return [anotherKey,i]
}
m[nums[i]] = i
}
return []
}
}
let s = Solution.init()
s.twoSum([3,3,6,8], 6)
2020.9.3
- 问:求第n个斐波那契数
- 思路
0 1 1 2 3 5 8 13 ....
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。定义:F(0) = 0,F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
- 代码(递归法)
func fib(_ index:Int) -> Int {
if index <= 1 {
return index;
}
return fib(index-1) + fib(index-2)
}
func fib2(_ n:Int) -> Int {
if n <= 1 {
return n
}
var first = 0
var second = 1
for _ in 0...n-2 {
let sum = first + second
first = second
second = sum
}
return second
}//时间复杂度O(n)
2020.9.14(滑动窗口)
- 问:给定一个字符串,找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
- 思路:“滑动窗口”思想。
- 滑动窗口就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列。
- 右边界不断的右移,只要没有重复的字符,就持续向右扩大窗口边界。一旦出现了重复字 符,就需要缩小左边界,直到重复的字符移出了左边界,然后继续移动滑动窗口的右边界。以此类推, 每次移动需要计算当前⻓度,并判断是否需要更新最大⻓度,最终最大的值就是题目中的所求。
- 代码:需要处理字符串,所用时间比较长。每次碰到重复的就对字符串处理。进行截取。重复判断字符串是否是最大长度
func lengthOfLongestSubstring(_ s:String ) -> Int {
if s.count == 1 {return 1}
if s.count == 0 {return 0}
var maxString = String()
var curString = String()
for char in s {
while curString.contains(char) {
curString.remove(at: curString.startIndex)
}
curString.append(char)
if curString.count > maxString.count{
maxString = curString
}
}
return maxString.count;
}
- 代码:数组做临时的存储,当碰到重复字符,删除此字符在数组之前所有字符,包括本身。
每次重复需要判断下是否是最大长度。
func lengthOfLongestSubstring(_ s:String) -> Int {
var charArray = Array<Character>()
var maxLenth = 0
for char in s {
if charArray.contains(char) {
let oldCharIndex:Int? = charArray.firstIndex(of: char)
charArray.removeFirst(oldCharIndex! + 1)
}
charArray.append(char)
if charArray.count > maxLenth {
maxLenth = charArray.count
}
}
return maxLenth
}
2020.9.14(滑动窗口)
- 问:给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
- 思路
这一题是滑动窗口的题目,在窗口滑动的过程中不断的包含字符串 T,直到完全包含字符串 T 的字符以 后,记下左右窗口的位置和窗口大小。每次都不断更新这个符合条件的窗口和窗口大小的最小值。最后输出结果即可。
- 代码
func minWindow2(_ s:String,_ t:String) -> String {
let sArray = [Character](s)
var window:Dictionary = Dictionary<Character,Int>() //保存滑动窗口字符集
var need:Dictionary = Dictionary<Character,Int>() //保存需要的字符集
for char in t{
need[char,default:0] += 1
}
var left = 0,right = 0 //窗口左右
var start = 0,end = 0
var match:Int = 0 //match匹配次数
var minLenth:Int = Int.max
while right < sArray.count {
let rightItem = sArray[right]
right += 1
//如果在需要的字符集内,添加到窗口字符集
if need[rightItem] != nil {
window[rightItem,default:0] += 1
//如果当前字符的数量匹配需要的字符数量,则match值+1
if window[rightItem] == need[rightItem] {
match += 1
}
}else {
continue
}
//当所有字符都匹配结束后,开始缩紧窗口
while match == need.count {
if right - left < minLenth {
start = left
end = right
minLenth = end - start
}
let leftItem = sArray[left]
left += 1
if need[leftItem] != nil {
// 左指针指向字符数量和需要的字符相等时,右移之后match值就不匹配则减一
// 因为window里面的字符数可能比较多,如有10个A,但需要的字符数量可能为3
if window[leftItem] == need[leftItem] {
match -= 1
}
window[leftItem]! -= 1
}
}
}
return minLenth == Int.max ? "" : String(sArray[start..<end])
}
2020.9.14(二分查找和二分搜索)