1. 程式人生 > >劍指offer十題刷(三)

劍指offer十題刷(三)

1、找一個只出現一次的數,其餘的數都出現兩次

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

說明:
你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?
示例 1:

輸入: [2,2,1]
輸出: 1
示例 2:

輸入: [4,1,2,1,2]
輸出: 4

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        size_t i=0;
        int num=0;
        for
(i=0;i<nums.size();i++) { num^=nums[i]; } return num; } };

2、字元排列組合

給定一個僅包含數字 2-9 的字串,返回所有它能表示的字母組合。
給出數字到字母的對映如下(與電話按鍵相同)。注意 1 不對應任何字母。
在這裡插入圖片描述
示例:

輸入:“23”
輸出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
說明:
儘管上面的答案是按字典序排列的,但是你可以任意選擇答案輸出的順序。
在這裡插入圖片描述

// 建立數字對映的字串陣列
string letterMap[10] = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" }; class Solution { public: // 核心思想:總計深度為digits.size()層的遞迴, // 每層遞迴在字串中一個字元進行組合。 void combineStr(const string& digits, size_t index, const string& str, vector<string>& strs) { if (index ==
digits.size()) { strs.push_back(str); return; } // 獲取數字對應的字元陣列 string letters = letterMap[digits[index] - '0']; for (size_t i = 0; i < letters.size(); ++i) { combineStr(digits, index + 1, str + letters[i], strs); } } vector<string> letterCombinations(string digits) { vector<string> strs; if (digits.empty()) return strs; size_t index = 0; string str; // 遞迴子問題組合字串 combineStr(digits, index, str, strs); return strs; } };

3、楊輝三角

給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。
在這裡插入圖片描述
在楊輝三角中,每個數是它左上方和右上方的數的和。

示例:

輸入: 5
輸出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> vv;//vv可以看做是vector中的每個元素也是vector
        vv.resize(numRows);//設定二維陣列的行數
        
        //逐行遍歷,開闢空間
        for(size_t v=0;v<numRows;++v)
        {
            vv[v].resize(v+1,0);//第0行有0+1個數據
            //第一列和最後一列都是1
            vv[v][0]=1;
            vv[v][v]=1;
        }
        for(size_t v=0;v<vv.size();++v)//行
        {
            for(size_t i=0;i<vv[v].size();++i)//列
            {
                if(vv[v][i]==0)
                    vv[v][i]=vv[v-1][i-1]+vv[v-1][i];
            }
        }
        return vv;
    }
};

4、字串(僅考慮字母和數字字元)是否是迴文,忽略字母大小寫。

給定一個字串,驗證它是否是迴文串,只考慮字母和數字字元,可以忽略字母的大小寫。

說明:本題中,我們將空字串定義為有效的迴文串。

示例 1:

輸入: “A man, a plan, a canal: Panama”
輸出: true
示例 2:

輸入: “race a car”
輸出: false

思路一 :原(0——9)的ascll碼值%32與原(A——Z)的ascll碼值%32有重合部分。而原字元-‘A’之後,(0——9)的ascll碼值都變成了負數,且不影響字母%32的結果。

在這裡插入圖片描述

class Solution {
public:
    bool isPalindrome(string s) {
        if (s.empty())
			return true;
		int begin = 0;
		int end = s.size() - 1;

		while (begin < end)
		{
			// 從前往後找一個數字字元或者字母
			while (begin != end)
			{
				if (IsNumberOrLetter(s[begin]))
					break;
				++begin;
			}
			// 從後往前找一個數字字元或者字母
			while (begin < end)
			{
				if (IsNumberOrLetter(s[end]))
					break;
					--end;
			}
			if (begin < end)
			{
				// 檢測start和end位置字元是否相等 或者是否不區分大小的相等
				if ((s[begin] + 32 - 'a') % 32 != (s[end] + 32 - 'a') % 32)
					return false;
				++begin;
				--end;
			}
		}
		return true;
	}
	bool IsNumberOrLetter(char c)
	{
		if (c >= '0' && c <= '9' ||
			c >= 'a' && c <= 'z' ||
			c >= 'A' && c <= 'Z')
		{
			return true;
		}
		return false;
	}
};
思路二 :那麼題設忽略大小寫,為了區分大寫字母和數字字元,可以將大寫字母全部轉換成小寫,更加方便地比較判斷。
class Solution {
public:
    bool NumOrStr(char c)//判斷一個字元是不是字母或者數字字元,如果是就要滿足迴文條件
    {
        if((c>='0'&&c<='9')||(c>='a'&&c<='z'))
            return true;
        return false;
    }
    bool isPalindrome(string s) {
        if(s.empty())return true;
        
        //因為提示忽略大小寫,將大寫字母統一改成小寫,方便比較
        size_t begin=0,end=s.size()-1;
        while(begin<=end){
            if(s[begin]>='A'&&s[begin]<='Z')
                s[begin]+=32;
            ++begin;
        }
        
        begin=0;
        while(begin<end)
        {
        	//從前向後尋找第一個滿足條件的字元
            while(begin<end)
            {
                if(NumOrStr(s[begin]))
                    break;
                begin++;
            }
            //從後向前尋找第一個滿足條件的字元    
            while(begin<end)
            {
                if(NumOrStr(s[end]))
                   break;
                end--;
            }
            
            if(begin<end)//如果begin==end,如“a.”直接跳過,return true
            {
                //到這個位置s[begin]和s[end]都是字母或者數字字元,只需驗證,二者是否相同
                if(s[begin]!=s[end])
                    return false;
                begin++,end--;
            }
        }
        return true;
    }
}

5、給定兩個字串形式的非負整數 num1 和num2 ,計算它們的和。

注意:
num1 和num2 的長度都小於 5100.
num1 和num2 都只包含數字 0-9.
num1 和num2 都不包含任何前導零。
你不能使用任何內建 BigInteger 庫, 也不能直接將輸入的字串轉換為整數形式。

class Solution {
public:
    string addStrings(string num1, string num2) {
        size_t l1=num1.size();
        size_t l2=num2.size();
        //以長字串作為外迴圈
        if(l1<l2){
            num1.swap(num2);
            swap(l1,l2);
        }
        int cret=0;
        int cstep=0;
        string str;
        str.reserve(l1+1);//保證空間足夠
        for(size_t i=0;i<l1;i++)
        {
            cret=num1[l1-i-1]-'0'+cstep;
            cstep=0;
            if(i<l2)
                cret+=num2[l2-i-1]-'0';
            if(cret>9){
                cstep=1;
                cret-=10;
            }
            str+=cret+'0';
        }
        if(cstep)//需要判斷,最後一位是否有進位
        	str+='1';
        reverse(str.begin(),str.end());//因為高位的值反而被放在了後面,所以要逆置
        return str;
    }
};

6、逆置前2k個字元的前k個字元

給定一個字串和一個整數 k,你需要對從字串開頭算起的每個 2k 個字元的前k個字元進行反轉。如果剩餘少於 k 個字元,則將剩餘的所有全部反轉。如果有小於 2k 但大於或等於 k 個字元,則反轉前 k 個字元,並將剩餘的字元保持原樣。

示例:

輸入: s = “abcdefg”, k = 2
輸出: “bacdfeg”
要求:

該字串只包含小寫的英文字母。
給定字串的長度和 k 在[1, 10000]範圍內。

string reverseStr(string s, int k) {
        for(int i = 0; i < s.length(); i += 2 * k){
            reverse(s.begin() + i, min(s.begin() + i + k, s.end()));
        }
        return s;
    }
string reverseStr(string s, int k) {
        for(int start = 0; start < s.size(); start += 2 * k){
            int i = start, j = min(start + k - 1, (int)s.size() -1);
            for(; i < j; i++, j--)
                swap(s[i],s[j]);
        }
        return s;
    }

7、有序二維陣列查詢一個數

在一個二維陣列中(每個一維陣列的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int l=array[0].size()-1;
        int h=0;
        while(h<array.size()&&l>=0)
        {
            if(target>array[h][l])
                h++;
            else if(target<array[h][l])
                l--;
            else 
                return true;
        }
        return false;
    }
};

8、逆序輸出連結串列中的val

輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> ArrayList;
        ListNode*cur=head;
        while(cur)
        {
            ArrayList.push_back(cur->val);
            cur=cur->next;
        }
       vector<int> result;
        for(int i=ArrayList.size()-1;i>=0;i--)
            result.push_back(ArrayList[i]);
        return result;
    }
};