本文按照牛客网的顺序,牛客网剑指offer刷题网址:https://www.nowcoder.com/ta/coding-interviews
本篇涉及的题目有:
1、和为S的两个数字
2、扑克牌顺子
3、求1+2+3+....+n
4、字符流中第一个不重复的字符
1、和为S的两个数字
问题描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
思路解析
由于是排好序的数组,因此对于和相等的两个数来说,相互之间的差别越大,那么乘积越小,因此我们使用两个指针,一个从前往后遍历,另一个从后往前遍历数组即可。
代码实现
java
import java.util.ArrayList;
public class Solution {
public ArrayList FindNumbersWithSum(int [] array,int sum) {
ArrayList arr = new ArrayList();
int left = 0;
int right = array.length - 1;
while(left < right){
if(array[left] + array[right] == sum){
arr.add(array[left]);
arr.add(array[right]);
return arr;
}
else if(array[left] + array[right] < sum)
left += 1;
else
right -= 1;
}
return new ArrayList();
}
}
python
# -*- coding:utf-8 -*-
class Solution:
def FindNumbersWithSum(self, array, tsum):
# write code here
if len(array) < 2:
return []
left = 0
right = len(array)-1
while left < right:
if array[left] + array[right] == tsum:
return [array[left],array[right]]
elif array[left] + array[right] > tsum:
right = right - 1
else:
left = left + 1
return []
2、扑克牌顺子
问题描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。
思路解析
分三步走
1、将数组排序
2、统计数组中0的个数,即判断大小王的个数
3、统计数组中相邻数字之间的空缺总数,如果空缺数小于等于大小王的个数,可以组成顺子,否则不行
注意到一点是,如果数组中出现了对子,那么一定是不可以组成顺子的。
代码实现
java
import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
if(numbers.length == 0)
return false;
Arrays.sort(numbers);
int zeros = 0;
for(int x:numbers)
if(x==0)
zeros++;
for(int i=zeros;izeros || numbers[i+1]==numbers[i])
return false;
else
zeros -= (numbers[i+1] - numbers[i] - 1);
}
return true;
}
}
python
# -*- coding:utf-8 -*-
class Solution:
def IsContinuous(self, numbers):
# write code here
if not numbers:
return False
numbers.sort()
zeros = 0
while numbers[zeros]==0:
zeros = zeros + 1
for i in range(zeros,len(numbers)-1):
if numbers[i+1] == numbers[i] or (numbers[i+1] - numbers[i] - 1) > zeros:
return False
else:
zeros -= (numbers[i+1]-numbers[i]-1)
return True
3、求1+2+3+....+n
问题描述
求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
思路解析
将加法问题转化为递归进行求解即可。
代码实现
java
public class Solution {
public int sum = 0;
public int Sum_Solution(int n) {
getSum(n);
return sum;
}
private void getSum(int n){
if(n<=0)
return;
sum += n;
getSum(n-1);
}
}
python
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.sum = 0
def Sum_Solution(self, n):
# write code here
if n<=0:
return 0
self.getSum(n)
return self.sum
def getSum(self,n):
self.sum+=n
n = n - 1
return n>0 and self.getSum(n)
4、不用加减乘除做加法
问题描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
思路解析
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 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为最终结果。
代码实现
java
public class Solution {
public int Add(int num1,int num2) {
while (num2!=0) {
int temp = num1^num2;
num2 = (num1&num2)<<1;
num1 = temp;
}
return num1;
}
}
python
# -*- coding:utf-8 -*-
class Solution:
def Add(self, num1, num2):
# write code here
while num2 != 0:
res = num1 ^ num2
carry = (num1 & num2) << 1
num1 = res
num2 = carry
return num1
4、字符流中第一个不重复的字符
问题描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
思路解析
用一个字典保存下出现过的字符,以及字符出现的次数。
除保存出现的字符之外,我们用一个字符数组保存出现过程字符顺序,如果不保存插入的char的话,我们可以遍历ascii码中的字符
代码实现
java
import java.util.*;
public class Solution {
//Insert one char from stringstream
public ArrayList charlist = new ArrayList();
public HashMap map = new HashMap();
public void Insert(char ch)
{
if(map.containsKey(ch))
map.put(ch,map.get(ch)+1);
else
map.put(ch,1);
charlist.add(ch);
}
//return the first appearence once char in current stringstream
public char FirstAppearingOnce()
{
char c='#';
for(char key : charlist){
if(map.get(key)==1){
c=key;
break;
}
}
return c;
}
}
python
# -*- coding:utf-8 -*-
class Solution:
# 返回对应char
def __init__(self):
self.s=''
self.dict1={}
def FirstAppearingOnce(self):
# write code here
for i in self.s:
if self.dict1[i]==1:
return i
return '#'
def Insert(self, char):
# write code here
self.s=self.s+char
if char in self.dict1:
self.dict1[char]=self.dict1[char]+1
else:
self.dict1[char]=1