java&python版剑指offer(七)

本文按照牛客网的顺序,牛客网剑指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<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> arr = new ArrayList<Integer>();
        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<Integer>();
    }
}

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;i<numbers.length-1;i++){
            if(numbers[i+1]-numbers[i]-1>zeros || 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<Character> charlist = new ArrayList<Character>();
    public HashMap<Character,Integer> map = new HashMap<Character,Integer>();
    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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270