今天刷的并不牢靠。第一题有点纠结太久了
感谢与参考:https://codingcat.cn/article/
不用加减乘除做加法
把字符串转换成整数
数组中重复的数字
字符流中第一个不重复的字符
不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
注意: 不能用四则运算符,那则只能是用最原始的二进制位运算。数值在计算机中的存储采用的是补码存储,所以一般的位运算都是基于补码进行的 二进制的加法运算,三步走:
第一步:相加各位的值,不算进位,即进行异或操作
第二步:计算进位值,进行与操作并左移一位
第三步,重复重复上述两步,当进位值为 0,则跳出循环。
具体到此题:
以用三步走的方式计算二进制值相加: 5即101,7即111
第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,即101^111。
第二步:计算进位值,得到1010,相当于各位做与操作(用&表示)得到101,再向左移一位得到1010,即(101&111) << 1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010) << 1。 继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
异或运算(操作)又叫半加运算,其运算法则相当于不带进位的二进制加法。二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法,用 ^ 表示
## C++ 语言版的
class Solution {
public:
int Add(int num1, int num2)
//#思路:二进制的运算。三步,第一步,异或运算,第二步,计算进位,与操作,左移一位。
//#第三步重复上述,直到进位为0
{
while(num2 !=0){
int temp=num1^num2; //与操作
num2=(num1&num2)<<1;//计算进位,并赋值给num2
num1=temp;
}
return num1;
}
};
C语言版本中int是32位的,进入下最后一个循环后,向左移一位后,最高位的1就溢出了,那一位就去了,如果原数后面第31位是0,则新的32位就变成了0. 但是python由于支持大int值,它的整数不是32位,而是某种程度上可以无限扩展,结果左移的1跑到33位,b仍然不是0,实际上永远也不是0,于是就无限循环了......
那么为了修正这个bug,我们必须截断b,让他保持最多32位,修改如下:
def getSum(a,b):
while b!=0:
ta = a
a = a^b #异或操作,
b = ((ta&b)<<1)&0xffffffff #与操作,截断b,让b保持最多32位
hibit = (a&0x80000000)>>31#a与上16进制中的 0x80000001 ,即与上二进制为1000 0000 0000 0000 0000 0000 0000 0000
#前三十一位都变为0了,再右移31位,记得到了原来数中第32位的值
if hibit==1:#如果第32为1,则原来的数为 负数了,需要按位取反+1,得到原值。
return -(((~a)+1)&0xffffffff)
else:
return a&0xffffffff
s=getSum(2,-5)
print(s)
把字符串转换成整数
题目描述
将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
注意:‘0’,'9'这样字符,其本质上存储也是用ASCII值存储的,字符‘0’对应48,字符'9'对应57
# -*- coding:utf-8 -*-
class Solution:
def StrToInt(self, s):
# write code here
#要注意考虑的全面性,注意细节的讨论
#需要回头看
minus = 1
number = 0
if not s:
return number
if s[0] == '+':
if len(s) > 1:
s = s[1:]
else:
return 0
elif s[0] == '-':
minus = -1
if len(s) > 1:
s = s[1:]
else:
return 0
for i in range(0, len(s)):
if '0' <= s[i] <= '9':
number = number * 10 + ord(s[i]) - ord('0')##ord(‘0’)将当个字符‘0’转换为其ASCII的整数值
else:
return 0
return number * minus
数组中重复的数字
问题
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
此题,需要再回头看看,尝试用字典存储key与频次value
思路 基本的思路就是建一个hash表,读数先判断是否重复,不重复就放进去读下一个,直到找到第一个重复的。 另外可以进行排序,然后判断是否有相邻两个数重复。
但注意题目中条件,所有数字都在0到n-1范围内。因此无需开辟额外空间,可以直接在数组上做标记。读到数字时,将数组中该数字作为下标的位置的数字,减去n,作为标记。下次读到相同数字,去其下标位置,发现数字值小于0,说明已经被标记过,那么这个就是重复数字了。
一些细节:之所以不用加上n的方法来标记,是因为可能会导致数字过大溢出(减去n就不会,因为只要n不溢出, -n-1 就不溢出, -n-1+一个正数 就也不会溢出)。也不能乘以-1来做标记,因为这种方法对0就没法做标记了。
# -*- coding:utf-8 -*-
class Solution:
# 返回值格式:函数返回True/False,找到任意重复的一个值并赋值到duplication[0]
def duplicate(self, numbers, duplication):
length = len(numbers)
for num in numbers:
if num >= 0:
# 直接按num为下标去找
index = num
else:
# 如果此处已被标记,则下标要按此处的值 num+length 去找
index = num + length
if numbers[index] < 0:
# 找到重复
duplication[0] = numbers[index] + length
return True
else:
# 不重复,则做下标记
numbers[index] -= length
return False
字符流中第一个不重复的字符
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
思路1:先扫一遍串,记下每个字符出现的次数,再扫一遍串同时查询每个字符出现的次数,遇到出现次数为1的就是第一个只出现一次的字符了。 思路2:可参考辛的笔记,还有蛮多方法的
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stream = []
self.counter = {}
# 返回对应char
def FirstAppearingOnce(self):
for c in self.stream:
if self.counter[c] == 1:
return c
return '#'
def Insert(self, char):
if char in self.counter:
self.counter[char] += 1
else:
self.counter[char] = 1
self.stream.append(char)