力扣题目(476、数字的补数)
题目:
给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。
注意:
- 给定的整数保证在32位带符号整数的范围内。
- 你可以假定二进制数不包含前导零位。
示例1:
输入: 5
输出: 2
解释: 5的二进制表示为101(没有前导零位),其补数为010。所以你需要输出2。
注意:
每个输入参数的边界满足 1 <= left <= right <= 10000
示例2:
输入: 1
输出: 0
解释: 1的二进制表示为1(没有前导零位),其补数为0。所以你需要输出0。
解题思路:
先将正整数转化为二进制数的形式
将二进制数取反
将二进制数转化为整数形式
熟练掌握:1、十进制数除二取余,直到为零,然后余数倒过来就是它的二进制数。
2、列表倒置的具体实现方法:就是在循环中,以索引位置的比较来完成第一个和最后一个互换、第二个与倒数第二个互换、。。。。
3、二进制转十进制:将它每个二进制位上的数乘以2的指数幂,其中2的指数幂根据二进制位来确定
代码实现:
class Solution:
def findComplement(self, num: int) -> int:
a = num
l=[]
s = 0
'''将十进制数取余,每取出一个余数就放入列表,直到为零,==特别注意此时余数是正着放进去的,不是该十进制数的二进制形式,因此还需要在下面进行倒转,才能得到这个十进制的二进制数形式=='''
while a > 0:
x = a%2 #除二取余
l.append(x) #将余数追加进列表
a //=2
'''将二进制数翻转回来,就是原十进制数的二进制形式,我们通过比较索引位置来实现(也就是列表中的倒置方法reverse())'''
for ind in range(len(l)):
lind = len(l)-1-ind
if ind < lind:
l[ind],l[lind] = l[lind],l[ind]
#将二进制位上的每一个数取反
for r in range(len(l)):
if l[r] == 1:
l[r] = 0
else:
l[r] = 1
#二进制转换为十进制:将二进制位上的数乘以2的指数幂(“个位”上的数是2的0次方,“十位”上的数是2的1次方。。。。。。)
for i in range(len(l)):
s += l[i]*(2**(len(l)-1-i))
return s
方法二:
也可以用bin()函数来完成,bin()函数会将十进制数转换位二进制,并以字符串的形式输出,格式为:"0b"+"二进制数"
我们可以通过字符串内置方法replace(),来将"0b"用空字符串""替换
代码实现:
class Solution:
def findComplement(self, num: int) -> int:
a=bin(num)
b=a.replace('0b','')
s = ''
c = 0
for i in b:
if i == '1':
s += '0'
else:
s += '1'
for i in range(len(s)):
c += int(s[i])*(2**(len(s)-1-i))
return c
力扣题目(961、重复 N 次的元素)
题目:
在大小为 2N
的数组 A
中有 N+1
个不同的元素,其中有一个元素重复了 N
次
返回重复了 N
次的那个元素
示例:
#示例1
输入:[1,2,3,3]
输出:3
#示例2
输入:[2,1,2,5,3,2]
输出:2
#示例3
输入:[5,1,5,2,5,3,5,4]
输出:5
提示:
4 <= A.length <= 10000
0 <= A[i] < 10000
A.length
为偶数
解题思路:
暴力算法:遍历元素,有相同的元素即返回该元素
代码实现:
class Solution:
def repeatedNTimes(self, A: List[int]) -> int:
s = 1
for i in range(len(A)):
for j in range(i+1,len(A)):
if A[i] == A[j]:
return A[i]
方法2:
通过实例分析:在有2n个元素的列表中,其中有n+1个不同元素,而有n个相同元素,那么相同的元素最大可能相隔的距离是3,再不可能有比这个距离更大的了
通过判断相邻、隔1个位置、隔2个位置的元素是否相同即可
class Solution:
def repeatedNTimes(self, A: List[int]) -> int:
i = 0
while i < len(A):
if (i+3)<len(A) and (A[i]==A[i+3] or A[i]==A[i+2] or A[i]==A[i+1]):
return A[i]
elif (i+2)<len(A) and (A[i]==A[i+2] or A[i]==A[i+1]):
return A[i]
elif (i+1)<len(A) and A[i]==A[i+1]:
return A[i]
else:
i += 1
总结:在编写程序的时候,不要形成固定的思路,需要突破惯性思维,打破传统,找到更多更简单的算法,比如这道题,我们一般是通过遍历所有元素来发现有相同的元素,而利用数学思想,可以知道在有一半相同元素且其他元素均不一样的情况下,相同元素的排列必定不可能突破相隔2个不同元素的底线(不相信的可以自己去算)
力扣(500、键盘行)
题目:
给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词
示例:
输入: ["Hello", "Alaska", "Dad", "Peace"]
输出: ["Alaska", "Dad"]
注意:
- 你可以重复使用键盘上同一字符。
- 你可以假设输入的字符串将只包含字母。
解题思路:
碰到判断一堆元素是否相同或来自同一区域的题型,我们一定要先将比对对象或比对区域统一格式,用字典将比对区域的所有元素进行归类(归为同一类)
然后再将判断对象转化为比对区域中的值进行判断(说的比较抽象,可以通过下面的代码进行思考、总结)
代码实现:
class Solution:
def findWords(self, words: List[str]) -> List[str]:
new_words = []
#将比对对象进行统一的归类
dic = {'q':0,'w':0,'e':0,'r':0,'t':0,'y':0,'u':0,'i':0,'o':0,'p':0,'Q':0,'W':0,'E':0,'R':0,'T':0,'Y':0,'U':0,'I':0,'O':0,'P':0,'a':1,'s':1,'d':1,'f':1,'g':1,'h':1,'j':1,'k':1,'l':1,'A':1,'S':1,'D':1,'F':1,'G':1,'H':1,'J':1,'K':1,'L':1,'z':2,'x':2,'c':2,'v':2,'b':2,'n':2,'m':2,'Z':2,'X':2,'C':2,'V':2,'B':2,'N':2,'M':2}
for s in words:
#将字符串s中的每一个字符都进行比较
for i in range(len(s)-1):
for j in range(i+1,len(s)):
if dic[s[i]] != dic[s[j]]:
new_words.append(s)
break #只要有不一样的字符就终止s中第一个元素与后续元素的比较
break #终止s中所有元素的相互比较
#删除有不同领域元素的字符串
for x in new_words:
words.remove(x)
return words