1. 程式人生 > >劍指offer系列(十五)和為S的連續正數序列,和為s的兩個數字,左旋轉字串

劍指offer系列(十五)和為S的連續正數序列,和為s的兩個數字,左旋轉字串

和為S的連續正數序列

題目描述

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

輸出描述:

輸出所有和為S的連續正數序列。序列內按照從小至大的順序,序列間按照開始數字從小到大的順序

解題思路:

設定兩個指標,先分別指向數字1和數字2,並設這兩個指標為small和big,對small和big求和,如果和大於目標值,
則從當前和中刪除small值,並把small值加一,如果和小於目標值,則把big值加一,再把新的big值加入和中。如果和等於
目標值,就輸出small到big的序列,同時把big加一併加入和中,繼續之前的操作。

舉例看起來更好理解一點,雖然是while迴圈裡面沒有做small到big之間的連線加減,但是由於都是從相鄰出發,加和都是基於
1 2 3相鄰數基礎之上的加和,大了就對第一個數不斷減,小了就對最後一個數不斷加即可。
舉例:輸入 tsum = 5
            1    2
            middle = 3   cursum = 3
            1 < 3:
                  3 < 5:
                       1     2    3
                       cursum = 1 + 2 + 3 = 6
                       6 > 5:
                            cursum - small = 6 - 1 = 5
                            return       2     3

程式碼:

# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        if tsum<3:
            return []
        small = 1
        big= 2
        middle = (tsum+1)//2
        cursum = big+small
        output = []
        
        while small<middle:
            if cursum == tsum:
                output.append(list(range(small, big+1)))
            while cursum > tsum and small <middle:
                cursum -= small
                small +=1
                if cursum ==tsum:
                    output.append(list(range(small, big+1)))
            big+=1
            cursum += big
        return output
                
            

和為s的兩個數字

題目描述

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

輸出描述:

對應每個測試案例,輸出兩個數,小的先輸出。

解題思路:

設定兩個指標,一個指向陣列的起點,一個指向陣列的終點,然後對兩個數字求和,如果和大於目標值,則把後一個指標前移,
如果和小於目標值,則把前一個指標後移。兩個指標交匯的時候如果還沒找到,就終止操作。

程式碼:

# -*- coding:utf-8 -*-
class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        if array == None or len(array)<=0 or array[-1]+array[-2]<tsum:
            return []
        start =0
        end = len(array)-1
        while start<end:
            if array[start]+array[end]<tsum:
                start +=1
            elif array[start]+array[end]>tsum:
                end -=1
            else:
                return [array[start], array[end]]
        return []

左旋轉字串

題目描述

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

解題思路:

法一:陣列字串的切分

法二:對原字串進行擴充兩倍,在這個基礎上直接從要反轉的地方取就可以,相當於前n個字串翻轉了,思想非常好

法三:首先需要寫一個reverse函式,把任何輸入的字串完全翻轉。然後根據題目中給出的左旋轉字串的個數n,
用全字串長度length減去旋轉字串個數n,求得對於新的字串應該在哪一位進行旋轉,然後分別旋轉前[:length-n]子
串和[length-n:]子串,重新拼接兩個子串即可。

程式碼:

法一:

# -*- coding:utf-8 -*-
class Solution:
    def LeftRotateString(self, s, n):
        # write code here
        return s[n:]+s[:n]

法二:

# -*- coding:utf-8 -*-
class Solution:
    def LeftRotateString(self, s, n):
        # write code here
        if not s:
            return ''
        length = len(s)
        s+=s
        return s[n:length+n]
    

法三:

# -*- coding:utf-8 -*-
class Solution:
    def LeftRotateString(self, s, n):
        # write code here
        if not s or len(s)<n or n<0:
            return ''
        s = list(s)
        length = len(s)
        s = self.Reverse(s)
        s1 = self.Reverse(s[:length-n])
        s2 = self.Reverse(s[length-n:])
        result = ''.join(s1)+''.join(s2)
        return result
    
    def Reverse(self, s):
        start = 0
        end = len(s)-1
        while start < end:
            s[start], s[end]=s[end],s[start]
            start +=1
            end-=1
        return s