劍指offer 41-45

41.和為S的連續正數序列

小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。
但是他并不滿足于此,他在想究竟有多少種連續的正數序列的和為100(至少包括兩個數)。
沒多久,他就得到另一組連續正數和為100的序列:18,19,20,21,22。
現在把問題交給你,你能不能也很快的找出所有和為S的連續正數序列? Good Luck!

這個題最直觀的想法就是從1,2開始用枚舉法算出所有的連續正數序列的和,直到第一個數和第二個數的和大于我們要求的數,例如求到了50,51則算法結束。
那么有沒有更節省時間的方法呢,我們注意到,例如4,5,6,7和5,6,7,8他們之間是有重疊的部分的,所以我們可以從最原始的sum=1+2=3開始,當sum<target的時候,我們就將數組長度往后擴展一位,同時sum要加上這個新添加的數,當sum>target的時候,我們先減去數組的第一個數,再將數組前部縮短一位,直到左右兩個指針重合的時候循環結束。
代碼如下

import java.util.ArrayList;
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        if(sum<=1){
            return new ArrayList<ArrayList<Integer>>();
        }
        int l = 1,h = 2,Sum = 3;
        ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>(); 
        //當l和h相等時中止循環
        while(l<h){
            //和小于sum時h往前走一位,且記得Sum += h
            //和大于sum時先Sum -= l,l再往前走一位
            //和等于sum時存下這個數組,然后h再往前走一位循環繼續
            if(Sum<sum){
                h++;
                Sum += h;
            }else if(Sum>sum){
                Sum -= l;
                l++;
            }else if(Sum==sum){
                ArrayList<Integer> tmp = new ArrayList<Integer>();
                for(int i=l;i<=h;i++){
                    tmp.add(i);
                }
                ret.add(tmp);
                h++;
                Sum += h;
            }
        }
        return ret;
    }
}

42.和為S的兩個數字

輸入一個遞增排序的數組和一個數字S,在數組中查找兩個數,使得他們的和正好是S,如果有多對數字的和等于S,輸出兩個數的乘積最小的。

這個題就很簡單了,41題的終極簡化版,用左右指針逼近就可以了,至于乘積最小的兩個數,用兩個變量去保村更新那和為S的數就可以了
代碼寫的有點冗余

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        if(array.length<=1){
            return new ArrayList<Integer>();
        }
        int l = 0,h = array.length-1;
        boolean flag = false;
        //初始化這個乘積,初始化兩個變量
        int mul = (int)Math.pow(array[array.length-1],2),first = array[0],last = array[array.length-1];
        while(l<h){
            if(array[l]+array[h]>sum){
                h--;
            }else if(array[l]+array[h]<sum){
                l++;
            }else{
                flag = true;
                if(array[l]*array[h]<=mul){
                    mul = array[l]*array[h];
                    first = array[l];
                    last = array[h];
                }
                l++;
            }
        }
        ArrayList<Integer> ret = new ArrayList<Integer>();
        ret.add(first);
        ret.add(last);
        if(flag){
            return ret;
        }else{
            return new ArrayList<Integer>();
        }
    }
}

43.左旋字符串

匯編語言中有一種移位指令叫做循環左移(ROL),現在有個簡單的任務,就是用字符串模擬這個指令的運算結果。
對于一個給定的字符序列S,請你把其循環左移K位后的序列輸出。
例如,字符序列S=”abcXYZdef”,要求輸出循環左移3位后的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它!

這個題就直接算出n對字符串長度取余得到N,將字符串的前N位放在最后就好了
代碼如下

public class Solution {
    public String LeftRotateString(String str,int n) {
        if(str.length()==0){
            return str;
        }
        char[] ch = str.toCharArray();
        int l = n%ch.length;
        char[] ret = new char[ch.length];
        int cnt = 0;
        //旋轉
        for(int i = l;i<ch.length;i++){
            ret[cnt] = ch[i];
            cnt++;
        }
        for(int j = 0;j<l;j++){
            ret[cnt] = ch[j];
            cnt++;
        }
        //拼接
        String res = "";
        for(char k:ret){
            res += k;
        }
        return res;
    }
}

44.翻轉單詞順序列

牛客最近來了一個新員工Fish,每天早晨總是會拿著一本英文雜志,寫些句子在本子上。同事Cat對Fish寫的內容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。例如,“student. a am I”。后來才意識到,這家伙原來把句子單詞的順序翻轉了,正確的句子應該是“I am a student.”。Cat對一一的翻轉這些單詞順序可不在行,你能幫助他么?

直接用Split將字符串切割成字符串數組就行
String[] res = str.split(" ")
然后逆序將字符串數組中res中字符串按逆序間隔空格拼接起來;
為了AC100%記住,要判定str是否為空字符串;

public class Solution {
    public String ReverseSentence(String str) {
        //切割
        String[] res = str.split(" ");
        if(res.length==0){
            return str;
        }
        String ret = "";
        //翻轉拼接
        for(int i = res.length-1;i>0;i--){
            ret += res[i]+" ";
        }
        ret += res[0];
        return ret;
    }
}

45.撲克牌順子

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的運氣如何, 如果牌能組成順子就輸出true,否則就輸出false。
為了方便起見,你可以認為大小王是0。

這個題的思路就是先對數組進行排序,然后統計數組中0的個數,再看后面的數組,一旦發現有兩個相等的數,就無法組成順子,直接返回false;然后統計兩兩數字之差減1然后求和,例如1,2之差是1,他們本身就已經是順子了,無需用0來填補,而1,4則需要兩個0,即4-1-1,最后統計完這個和sum小于等于0的個數的話,那么就可以組成順子
代碼流程如下

1.排序
2.初始化變量cnt_0用來計算0的個數;初始化一個tmp變量用來存儲上一個非0的數字;初始化一個變量sum來記錄差值的和
3.遍歷排序數組{
        如果當前數等于0{
                cnt_0++;
        }否則{
                如果tmp等于0{
                        tmp = num;
                }否則{
                        如果num==tmp{
                                返回false
                        }否則{
                                sum += num-tmp-1;
                                tmp = num;
                        }
                }
        }
}
4.判斷sum是否小于cnt_0,即是否有足夠的癩子可以填充空缺

代碼如下

import java.util.Arrays;
public class Solution {
    public boolean isContinuous(int [] numbers) {
        if(numbers.length==0){
            return false;
        }
        Arrays.sort(numbers);
        int cnt_0 = 0;
        int tmp = 0;
        int sum = 0;
        for(int num:numbers){
            if(num==0){
                cnt_0++;
            }else{
                if(tmp==0){
                    tmp=num;
                }else{
                    if(num==tmp){
                        return false;
                    }else{
                        sum += num-tmp-1;
                        tmp = num;
                    }
                }
            }
        }
        if(sum<=cnt_0){
            return true;
        }else{
            return false;
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容