★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10978800.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
1、寻找重复出现奇数次的数字。
给定一个整形数组,其中只有一个数字出现奇数次,其他数字出现偶数次。找出这个数字?
思考:两个相同的整数异或为零,一个整数和0异或为其本身。异或可以使用交换律和结合律。
例:数组[1,1,2,2,2,3,3,3,3]求出现了奇数次的数字。
1^1^2^2^2^3^3^3^3
=(1^1)^(2^2)^2^(3^3)^(3^3)
=0^0^2^0^0
=2
Talk is cheap.Show me your code:
1 //测试用例 2 let arr = [1,1,2,2,2,3,3,3,3] 3 //打印 4 print(arr.reduce(0,^)) 5 //Print 2
2、不使用额外辅助变量,如何交换两个整型变量x和变量y的值?
思考:异或可以使用交换律和结合律。
1 x = x ^ y (1) 2 y = x ^ y (2) 3 x = x ^ y (3)
证明:将式1分别代入式2、式3
1 y = x^y = (x^y)^y = x^(y^y) = x^0 = x 2 x = x^y = (x^y)^x = (x^x)^y = 0^y = y
Talk is cheap.Show me your code:
1 func swap(_ x:inout Int,_ y:inout Int) 2 { 3 x = x ^ y 4 y = x ^ y 5 x = x ^ y 6 }
测试:
1 var x:Int = 1 2 var y:Int = 9 3 swap(&x,&y) 4 print(x) 5 //Print 9 6 print(y) 7 //Print 1
3、不使用pow库函数,求m的n次方?
例:求m的7(二进制:111)次方?
可以拆解为:m^7=(m^100)*(m^010)*(m^001)
通过[&1]和[>>1]来逐位读取指数,为1时将该位代表的指数累乘到最终结果中。
Talk is cheap.Show me your code:
1 func newPow(_ m:Int,_ n:Int) -> Int 2 { 3 var m = m 4 var n = n 5 var sum:Int = 1 6 while(n != 0) 7 { 8 if n & 1 == 1 9 { 10 sum *= m 11 } 12 m *= m 13 n = n >> 1 14 } 15 return sum 16 }
测试:
1 print(newPow(3,4)) 2 //print 81
4、取模运算和取余运算的区别
取余运算和取模运算的步骤相同。
对于整数a、b。计算a%b:
(1)、求商: c = a/b;
(2)、计算模或余数: r = a - c*b.
求模运算和求余运算在第一步不同:
取余运算在取c的值时,向0方向舍入;
取模运算在计算c的值时,向-∞方向舍入。
%在Swift、C、C++,Java 中称为余运算符,在Python中成为的模运算符。
取余运算:Swift、C、C++,Java
取模运算:Python
Swift是取余运算。若b负值,忽略b的符号。即:a % b = a % (-b)
[总结]
当a和b符号一致时:
取余运算和取模运算所得结果一致。
当a和b符号不一致时:
取余运算结果和a符号一致。
取模运算结果和b符号一致。
测试:
1 print(6%4) 2 print(-6%4) 3 print(6%(-4)) 4 //Print 2 5 //Print -2 6 //Print 2
5、数组下标(计数排序):统计数字、判断字母出现次数。
给定一个整形数组,数组元素的取值范围0~100。
请用O(n)时间复杂度,从小到大打印出来?
思路:把对应的数值作为数组下标,如果这个数出现过,则对应的数组加1。
Talk is cheap.Show me your code:
1 func printNum(_ arr:[Int],_ maxNum:Int) 2 { 3 var temp:[Int] = [Int](repeating: 0, count: maxNum + 1) 4 for i in 0..<arr.count 5 { 6 temp[arr[i]] += 1 7 } 8 for i in 0...maxNum 9 { 10 for j in 0..<temp[i] 11 { 12 print("(j):(i)") 13 } 14 } 15 }
测试:
1 let arr:[Int] = [100,5,71,89,66,77,89,91,71,95,5,100] 2 printNum(arr, 100) 3 /* 4 0:5 5 1:5 6 0:66 7 0:71 8 1:71 9 0:77 10 0:89 11 1:89 12 0:91 13 0:95 14 0:100 15 1:100 16 */
5、递归(n->1)和递推(1->n)
青蛙一次可以跳1级台阶或2级台阶。求该青蛙跳上n级的台阶有多少种跳法?
递归(n->1)法:很多重复计算
1 func jump(_ n:Int) -> Int 2 { 3 if n <= 2 {return n} 4 else 5 { 6 return jump(n - 1) + jump(n - 2) 7 } 8 }
测试:
1 print(jump(10)) 2 //print 89
备忘录法:巧用数组下标,去除重复计算
当arr[n] = 0时,表示jump(n)未计算,
当arr[n] != 0时,表示jump(n)已计算。
1 func jump(_ n:Int) -> Int 2 { 3 var arr:[Int] = [Int](repeating: 0, count: 1) 4 if n <= 2 {return n} 5 else 6 { 7 //数组自动扩容 8 while(n > arr.count - 1) 9 { 10 arr += [Int](repeating: 0, count: arr.count) 11 } 12 //未计算 13 if arr[n] == 0 14 { 15 arr[n] = jump(n-1) + jump(n-2) 16 return arr[n] 17 } 18 else 19 { 20 //已计算 21 return arr[n] 22 } 23 } 24 }
测试:
1 print(jump(10)) 2 //print 89 3 print(jump(11)) 4 //print 144
递推(1->n)法:
1 func jump(_ n:Int) -> Int 2 { 3 if n <= 2 {return n} 4 var n1:Int = 1 5 var n2:Int = 2 6 var sum:Int = 0 7 for _ in 3...n 8 { 9 sum = n1 + n2 10 n1 = n2 11 n2 = sum 12 } 13 return sum 14 }
测试:
1 print(jump(10)) 2 //print 89 3 print(jump(11)) 4 //print 144 5 print(jump(12)) 6 //print 233
使用递归时常考虑以下问题:
(1). 是否有重复计算,可使用备忘录法来优化。
(2). 是否可采取递推(1->n)的方法,减少递归的开销。