题目1:
求 1+2+...+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
思路:这一题如果没有限制条件那是非常简单的,但是题目要求我们不能使用关键字和乘除法,不过递归肯定还是这一道题的破解之处,我们只需要找到一个关键点,那就是什么时候递归截至。除了条件判断之外还有一个方法可以用来判断截至,那就是或运算和与运算,a&&b,如果a 是假的,&&后面的就不会执行,这就是我们的突破口。
代码:
class Solution:
def __init__(self):
self.res=0
def sumNums(self, n: int) -> int:
#通过逻辑and来进行递归的终止,n>1 and self.sumNums(n-1),
#如果n>1不成立的话,那后面这个就不会运行
n > 1 and self.sumNums(n - 1)
self.res+=n
return self.res
题目二:
给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B[i] 的值是数组 A 中除了下标 i 以外的元素的积, 即 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
示例:
输入: [1,2,3,4,5]
输出: [120,60,40,30,24]
思路:如果可以使用除法的话那我们就会很简单的写出来这一道题,只需要在b数组的相应位置除以a数组中相应位置的值就可以了。但是题目中有限制,那我们这时候就会考虑暴力解法了,每一个值除了相应位置的不用乘,其他位置的依次相乘,这样很简单,但是肯定还是超时的,所以还要想其他的方法。这里我们可以使用一个数组的表格分区来写,将a数组和b数组写在一个表格中,第一次遍历表格的时候就算出来对角线左边的b[i]的值,倒着遍历回来的时候,再算出来真正的b[i]的值。
这里引用一下k神的图片
第一次遍历的时候,依次算出来的是对角线左下角的绿色的a[i]的乘积,然后再倒着遍历一遍,将刚才b[i]的结果再乘上右上角部分的值,就得到最终的答案。
代码:
class Solution:
def constructArr(self, a: List[int]) -> List[int]:
#不可以使用除法,但是又不能直接暴力求解那样肯定是超时的
#所以可以构建一个表格分区,分别求出来以对角线分开的上三角和下三角的值
#根据需要将它们乘在一起
length=len(a)
temp=0
b=[1]*length
#计算下三角的值
for i in range(1,length):
b[i]=b[i-1]*a[i-1]
#计算上三角的值
for i in range(length-2,-1,-1):
temp*=a[i+1]
b[i]*=temp
return b
题目三:
写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
示例:
输入: a = 1, b = 1
输出: 2
思路:这一道题的思路可以参考数电中的加法器原理,s=a^b(不管进位的加法值为s,a和b的异或得到),c=a&b,进位的值是c,由a和b相与得到。然后我们就一直循环这个加法器,直到进位的值变成了0,就跳出循环,得到加法的值。
代码:
class Solution:
def add(self, a: int, b: int) -> int:
x = 0xffffffff
a, b = a & x, b & x
c=0
n=0
#循环过去直到进位为0
while 1:
c=(a&b)<<1 & x
n=a^b
a=c
b=n
if c==0:
break
return n if n <= 0x7fffffff else ~(n ^ x)
python中负数需要注意的地方,和其他语言不太相同,上面的x也是这个原因
'''
Python,Java 等语言中的数字都是以 补码 形式存储的。但 Python 没有 int , long 等不同长度变量,即在编程时无变量位数的概念。
获取负数的补码: 需要将数字与十六进制数 0xffffffff 相与。可理解为舍去此数字 32 位以上的数字(将 32 位以上都变为 00 ),从无限长度变为一个 32 位整数。
返回前数字还原: 若补码 aa 为负数( 0x7fffffff 是最大的正数的补码 ),需执行 ~(a ^ x) 操作,将补码还原至 Python 的存储格式。 a ^ x 运算将 1 至 32 位按位取反; ~ 运算是将整个数字取反;因此, ~(a ^ x) 是将 32 位以上的位取反,1 至 32 位不变。
'''



