日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

剑指 offer 编程题 C++ 版总结(中)

發布時間:2024/2/28 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 剑指 offer 编程题 C++ 版总结(中) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解題思路:從根結點開始向下進行對比,(1) 若兩邊的結點為空,返回 true。(2) 一個結點為空,而另一個結點不為空,此時二叉樹不是對稱的,返回 false。(3) 兩邊結點都不為空,但是結點的值不相等,返回 false。當這三種情況判斷完了后,開始判斷左右子樹是否滿足對稱條件。

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:bool isSymmetric(TreeNode* root) {return isSymmetric(root, root);}bool isSymmetric(TreeNode* T1, TreeNode* T2){if(T1 == NULL && T2 == NULL)return true;if(T1 == NULL || T2 == NULL)return false;if(T1->val != T2->val)return false;return isSymmetric(T1->left, T2->right) && isSymmetric(T1->right, T2->left);} };

?

?

解題思路:可以將矩陣看成若干層,首先打印最外層的元素,其次打印次外層的元素,直到打印最內層的元素。對于每層,從左上方開始以順時針的順序遍歷所有元素。假設當前層的左上角位于 (top,left),右下角位于 (bottom,right),按照如下順序遍歷當前層的元素。

class Solution { public:vector<int> spiralOrder(vector<vector<int>>& matrix) {if (matrix.size() == 0 || matrix[0].size() == 0) {return {};}int rows = matrix.size(), columns = matrix[0].size();vector<int> order;int left = 0, right = columns - 1, top = 0, bottom = rows - 1;while (left <= right && top <= bottom) {for (int column = left; column <= right; column++) {order.push_back(matrix[top][column]);}for (int row = top + 1; row <= bottom; row++) {order.push_back(matrix[row][right]);}if (left < right && top < bottom) {for (int column = right - 1; column > left; column--) {order.push_back(matrix[bottom][column]);}for (int row = bottom; row > top; row--) {order.push_back(matrix[row][left]);}}left++; //這里比較好理解,就是4個量是收縮的狀態。right--;top++;bottom--;}//end whilereturn order;} };

時間復雜度:O(mn),其中 mm 和 nn 分別是輸入矩陣的行數和列數。矩陣中的每個元素都要被訪問一次。

空間復雜度:O(1)。除了輸出數組以外,空間復雜度是常數。

?

?

解題思路:用兩個棧完成該功能,stack1 是用來存放正常的數據的,stack2 來記錄棧中最小的元素。當一個元素入棧時,stack1完成入棧操作。此時 stack2 需要根據情況完成相應的操作。若 stack2 為空或者入棧的元素小于等于 stack2 的棧頂元素,則 stack2 也完成入棧操作。反之,將 stack2 棧頂元素再入棧。出棧時,兩個棧都要完成 pop 操作。獲取最小值的操作通過獲取 stack2 棧頂元素即可。

class MinStack { public:/** initialize your data structure here. */stack<int> data, help;MinStack() {}void push(int x) {data.push(x);// 如果x是data和help的第一個元素,或者x小于等于help的最小元素,入棧if(help.empty() || x <= help.top()) help.push(x);if(x > help.top()){// 如果x大于help的最小元素,向help中再壓入一遍該最小元素,保持兩個棧元素個數相等// 比如data里現在有3,help里現在也有3,data里壓入一個4,那么help里壓入一個3// 這樣如果把data的4彈出,我們同步把help的3也彈出int temp = help.top();help.push(temp);}}void pop() {if(!data.empty() && !help.empty()){data.pop();help.pop();}}int top() {return data.top();}int min() {return help.top();} };

?

?

解題思路:該題會用到兩種數據結構,分別是棧和隊列。用隊列存儲棧的彈出序列,用棧存儲棧的壓入序列。開始的時候,先將彈出序列全部入隊。接著,將壓入序列逐個入棧。當棧的棧頂元素和隊的隊首元素相同時,兩者同時完成 pop 操作。若最終棧為空,則說明第二個序列是棧的彈出序列。反之,則不是。

class Solution { public:bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {stack<int>S;queue<int>Q;for(int i = 0; i < popped.size(); ++i){//Pop序列入隊Q.push(popped[i]);}for(int i = 0; i< pushed.size(); ++i){ //Push序列入棧S.push(pushed[i]); //push序列入棧,然后和隊首元素進行比較while(!S.empty() && S.top() == Q.front()){ //棧不空,同時棧的top等于隊列的frontQ.pop(); //兩者都popS.pop();}}if(!S.empty()){return false;}return true;} };

?

?

解題思路:就是二叉樹的層次遍歷,需要用到隊列。先將根結點入隊,然后每次取隊首元素將其存到 vector 中,然后再將左子樹和右子樹分別入隊(循環結束的標志是隊為空)。

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:vector<int> levelOrder(TreeNode* root) {vector<int> result;if(root == NULL)return result;queue<TreeNode*> que;TreeNode* p = root;que.push(p);while(!que.empty()){p = que.front();que.pop();result.push_back(p->val);if(p->left != NULL)que.push(p->left);if(p->right != NULL)que.push(p->right);}return result;} };

?

?

解題思路:是二叉樹層次遍歷的變形。該題需要在上一題的基礎上獲取遍歷到每一層時隊列的長度,即該層有多少個元素。然后可以寫一個 for 循環將該層的元素添加到一個 vector 中,遍歷完每一層后需要 vector 添加到一個二維 vector 中。

class Solution { public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;vector<int> asd;if(root == NULL)return result;queue<TreeNode*> que;TreeNode* p = root;que.push(p);while(!que.empty()){int size = que.size();for(int i = 0; i < size; i++){p = que.front();que.pop();asd.push_back(p->val);if(p->left != NULL)que.push(p->left);if(p->right != NULL)que.push(p->right);}result.push_back(asd);asd.clear();}return result;} };

?

?

解題思路:在上一題的基礎上,設置一個記錄層數的變量。根據層數的奇偶多加一個 reverse 操作即可。

class Solution { public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;vector<int> asd;if(root == NULL)return result;queue<TreeNode*> que;TreeNode* p = root;que.push(p);int count = 0;while(!que.empty()){int size = que.size();for(int i = 0; i < size; i++){p = que.front();que.pop();asd.push_back(p->val);if(p->left != NULL)que.push(p->left);if(p->right != NULL)que.push(p->right);}if(count % 2 == 0)result.push_back(asd);else{reverse(asd.begin(), asd.end());result.push_back(asd);}asd.clear();count++;}return result;} };

?

?

解題思路:二叉搜索樹(BST)的中序遍歷是有序序列。其后序遍歷結點的特性是結點值左 < 中 < 右。

class Solution { public:bool verifyPostorder(vector<int>& postorder) {if(postorder.empty()) return true;int len = postorder.size();return recursion(postorder, 0, len - 1);// 遞歸 + 利用 BST 后序遍歷節點值 左 < 中 < 右的特性}bool recursion(vector<int>& postorder, int left, int right){if(left >= right) return true; // 沒有左子樹(比如[5,4,3,2,1]),trueint root = postorder[right];int pos = left; // 必須要設置一個 pos 變量保存 left,不能直接操作 left!for(; pos < right; ++pos){// 找到右子樹起點if(postorder[pos] > root) break;}for(int j = pos; j<right; ++j){// 如果右子樹部分有小于 root 的,falseif(postorder[j] < root) return false;}// 看左子樹是否也是后序遍歷。如果前面不設置 pos 的話,這里就會是 (postorder,0,left-1),會嚴重超時if(!recursion(postorder, left, pos - 1)) return false; if(!recursion(postorder, pos, right - 1)) return false;// 看右子樹是否也是后序遍歷return true;} };

?

?

解題思路:該題使用 DFS 思路比較清晰。從上往下進行深度遍歷,每進入下一層時,sum 都要減去當前結點的 val。當遍歷到葉子結點的時候,若此時的 sum 和葉子結點的值相等,表明這是一條滿足條件的路徑。

/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:vector<vector<int>> ans;void DFS(TreeNode* root, vector<int>& t, int sum){if(root == nullptr)return;t.push_back(root->val);if(root->val == sum && root->left == nullptr && root->right == nullptr)// 是葉子節點且從根節點到葉子節點路徑總和=sum -> 符合題目的路徑ans.push_back(t);// if(root->left)DFS(root->left, t, sum - root->val);// if(root->right)DFS(root->right, t, sum - root->val);// 彈出最后一個元素t.pop_back();}vector<vector<int>> pathSum(TreeNode* root, int sum) {vector<int> t;DFS(root, t, sum);return ans;} };

?

?

(1) 首先觀察到題目給的是一棵 BST,這就意味著我們只需要用中序遍歷就能實現排序的鏈表了。 (2) 最終得到的鏈表的頭節點必然是 BST 最左邊的節點(題目示例中就是 1);尾節點必然是 BST 最右邊的節點。 (3) 我們先定義 *tail 和 *head,初始它們都是 nullptr,到最后則會一個指向尾節點一個指向頭節點。 (4) 所以我們中序遍歷,首先 root 一直往左走,走到了最左邊的 1 處,此時 tail 還是 nullptr,并且整個遍歷過程中只有這個時候 tail 會是 nullptr。這個時候我們讓 head = root,也就找到了鏈表的頭節點。 (5) 然后我們更新 tail = root(也就是 1),root 會回溯到上一級也就是 2。這時我們就寫 tail -> right = root; 和 root -> left = tail;。 (6) 我們此時接著更新 tail = root(也就是 2)。如此往復。 (7) 中序遍歷走完之后,鏈表也就構造完了,除了 head 和 tail 之間的連接,我們再連接一下就好了(代碼對應處有注釋)。

解題思路:

(1) 首先觀察到題目給的是一棵 BST,這就意味著我們只需要用中序遍歷就能實現排序的鏈表了。 (2) 最終得到的鏈表的頭節點必然是 BST 最左邊的節點(題目示例中就是 1);尾節點必然是 BST 最右邊的節點。 (3) 我們先定義 *tail 和 *head,初始它們都是 nullptr,到最后則會一個指向尾節點一個指向頭節點。 (4) 所以我們中序遍歷,首先 root 一直往左走,走到了最左邊的 1 處,此時 tail 還是 nullptr,并且整個遍歷過程中只有這個時候 tail 會是 nullptr。這個時候我們讓 head = root,也就找到了鏈表的頭節點。 (5) 然后我們更新 tail = root(也就是 1),root 會回溯到上一級也就是 2。這時我們就寫 tail -> right = root; 和 root -> left = tail;。 (6) 我們此時接著更新 tail = root(也就是 2)。如此往復。 (7) 中序遍歷走完之后,鏈表也就構造完了,除了 head 和 tail 之間的連接,我們再連接一下就好了(代碼對應處有注釋)。 /* // Definition for a Node. class Node { public:int val;Node* left;Node* right;Node() {}Node(int _val) {val = _val;left = NULL;right = NULL;}Node(int _val, Node* _left, Node* _right) {val = _val;left = _left;right = _right;} }; */ class Solution { private: Node* head, *tail; public:Node* treeToDoublyList(Node* root) {if(!root) {return nullptr;}inorder(root); // 構造出鏈表的所有結構,除了頭連尾和尾連頭的兩個指針head -> left = tail; // 補上頭連尾tail -> right = head; // 補上尾連頭return head; // 返回頭}void inorder(Node* root) {if(!root) {return;}inorder(root -> left); // 左if(!tail) {head = root; // 當tail還不存在,也就是root此時在整個BST的最左邊的節點,這個節點就是head}else {tail -> right = root; // 前一個節點的right是當前節點root -> left = tail; // 當前節點的left是前一個節點}tail = root; // 將前一個節點更新為當前節點(所以到最后,tail就會挪到整個BST的最右邊的節點,這個節點就是鏈表的尾節點)inorder(root -> right); // 右} };

?

?

解題思路:(1) 使用全排列的方法能夠列出所有的情況,但是題中說明了不能包含重復元素。所以可以在每次添加到二維數組的時候添加一個判斷條件,即調用 find 函數,看已經保存的組合中有沒有當前組合。但是這樣時間復雜度太大了,在力扣上會時間超出限制。

class Solution { private:vector<string> result; public:void permutation(vector<string> &asd, string &s , int k, int m){if(k == m){if( find(result.begin(), result.end(), s) == result.end() )asd.emplace_back(s);return;}else{for(int i = k; i < m; i++){swap(s[k], s[i]);permutation(asd, s, k+1, m);swap(s[k], s[i]);}}}vector<string> permutation(string s) {int size = s.size();permutation(result, s, 0, size);return result;} };

(2) 使用回溯法。

回溯法字符串的排列和數字的排列都屬于回溯的經典問題回溯算法框架:解決一個問題,實際上就是一個決策樹的遍歷過程:1. 路徑:做出的選擇2. 選擇列表:當前可以做的選擇3. 結束條件:到達決策樹底層,無法再做選擇的條件偽代碼:result = []def backtrack(路徑,選擇列表):if 滿足結束條件:result.add(路徑)returnfor 選擇 in 選擇列表:做選擇backtrack(路徑,選擇列表)撤銷選擇核心是for循環中的遞歸,在遞歸調用之前“做選擇”,在遞歸調用之后“撤銷選擇”。字符串的排列可以抽象為一棵決策樹:[ ][a] [b] [c][ab] [ac] [bc] [ba] [ca] [cb][abc] [acb] [bca] [bac] [cab] [cba]考慮字符重復情況:[ ][a] [a] [c][aa] [ac] [ac] [aa] [ca] [ca][aac] [aca] [aca] [aac] [caa] [caa]字符串在做排列時,等于從a字符開始,對決策樹進行遍歷,"a"就是路徑,"b""c"是"a"的選擇列表,"ab"和"ac"就是做出的選擇,“結束條件”是遍歷到樹的底層,此處為選擇列表為空。本題定義backtrack函數像一個指針,在樹上遍歷,同時維護每個點的屬性,每當走到樹的底層,其“路徑”就是一個全排列。當字符出現重復,且重復位置不一定時,需要先對字符串進行排序,再對字符串進行“去重”處理,之后按照回溯框架即可。 std::vector<std::string> permutation(std::string s) {if(s.empty()){return {};}// 對字符串進行排序std::sort(s.begin(), s.end());std::vector<std::string> res;// 標記字符是否遍歷過std::vector<bool> visit(s.size(), false);std::string track;backtrack(res, s, track, visit);return res; }/** 回溯函數* 使用sort函數對字符串排序,使重復的字符相鄰,* 使用visit數組記錄遍歷決策樹時每個節點的狀態,* 節點未遍歷且相鄰字符不是重復字符時,* 則將該字符加入排列字符串中,依次遞歸遍歷。* */ void backtrack(std::vector<std::string> &res, std::string s, std::string &track, std::vector<bool> &visit) {// 回溯結束條件if(track.size() == s.size()){res.push_back(track);return;}// 選擇和選擇列表for(int i = 0; i < s.size(); i++){// 排除不合法的選擇if(visit[i]){continue;}if(i > 0 && !visit[i-1] && s[i-1] == s[i]){continue;}visit[i] = true;// 做選擇track.push_back(s[i]);// 進入下一次決策樹backtrack(res, s, track, visit);// 撤銷選擇track.pop_back();visit[i] = false;} }

?

?

解題思路:設置一個計數器 count,每遇到一個和當前的數字相同的數字,就讓 count 自增,遇到一個和當前數字不一樣的數字,就讓 count--,當 count < 0 時,就將 cur 設置為當前遍歷的數字。因為有一個數字出現次數超過數組長度的一半,最后得到的必然是該數字。

class Solution { public:int majorityElement(vector<int>& nums) {int count = 1, cur = nums[0];for(int i = 1; i < nums.size(); i++) {if(cur != nums[i]) {--count;if(count < 0) {cur = nums[i];count = 1;}}else ++count;}return cur;} };

?

?

解題思路:找出序列中最小的 k 個數,這和 Top k 問題的解題思路一樣。構建一個含有 k 個元素的大頂堆。先將序列前 k 個元素放入堆中,剩余的元素入堆時需要滿足新加入的元素要小于堆頂元素。滿足該條件時,先 pop 堆頂元素,然后完成 push 操作。最終堆內的元素就是該序列的最小的 k 個元素。

class Solution { public:vector<int> getLeastNumbers(vector<int>& arr, int k) {int size = arr.size();vector<int> result;if(k == 0) return result;priority_queue<int, vector<int>, less<int>> asd;for(int i = 0; i < k; i++)asd.push(arr[i]);for(int i = k; i < size; i++){if(arr[i] < asd.top()){asd.pop();asd.push(arr[i]);}}while(k--){result.push_back(asd.top());asd.pop();}return result;} };

?

?

解題思路:比較簡單的動態規劃問題。使用 maxsum 記錄當前最大和,bestmax 是 maxsum 中最大的值。從前往后遍歷數組元素,當 maxsum 大于零時,令 maxsum += nums[i]。反之,令 maxsum = nums[i]。每遍歷完一個元素后,用 bestmax 記錄 maxsum 和 bestmax 中較大的值。

class Solution { public:int maxSubArray(vector<int>& nums) {int size = nums.size();int maxsum = 0, bestmax = INT_MIN;for(int i = 0; i < size; i++){if(maxsum > 0) maxsum += nums[i];else maxsum = nums[i];bestmax = std::max(maxsum, bestmax);}return bestmax;} };

?

?

解題思路:力扣上常規方法很難滿足時間要求,很多人給的答案都是通過找規律完成該題的。這里我只將它當成大數問題來做。

class Solution { public:int countDigitOne(int n) {string str = "0";int overten = 0, count = 0;while(n--){int temp;for(int i = 0; i < str.size(); i++){temp = str[i] - '0';temp = temp + 1;if(temp >= 10){temp -= 10;overten = 1;}elseoverten = 0;str[i] = temp + '0';if(overten == 0)break;}if(overten == 1)str.push_back('1');for(int i = 0; i < str.size(); i++){if(str[i] == '1')count++;}}return count;} };

?

?

解題思路:不管有多少個數,也不管這些數各自分別是幾位數(個位 / 十位 / 百位 / ...),我們的判斷方法只有一個。那就是先比較最高位,按照從小到大排即可。具體步驟如下:

(1)先比較這些數各自的最高位,按從小到大排。比如 "1"、"32"、"100",我們通過比較最高位可以排出:一開始是 "1" 或 "100",然后是 "32"。 (2)如果遇到了最高位數字相同的情況,比如上面的 "1" 和 "100",我們自定義比較方法:比較 字符串 1 + 字符串 2 與 字符串 2 + 字符串 1 的大小, 返回小的那個。在這里我們有 "1" + "100" = "1100" 和 "100" + "1" = "1001"。因為 "1001" < "1100",所以我們知道應該把 "100" 放第一位,"1" 放第二位,"32" 還是在最后。 (3)假如最高位沒有相同數字,那么根據最高位的排序直接就已經排好了。 class Solution { public:string minNumber(vector<int>& nums) {vector<string> strs;string ans;//將 int 轉變為 stringfor(int i = 0; i < nums.size(); i ++){strs.push_back(to_string(nums[i]));}//排序sort(strs.begin(), strs.end(), [](string& s1, string& s2){return s1 + s2 < s2 + s1;});for(int i = 0; i < strs.size(); i ++)ans += strs[i];return ans;}static bool strCompare(const string& s1, const string& s2) { // 注意 staticstring add1 = s1 + s2;string add2 = s2 + s1;return add1 < add2;} };

?

?

解題思路:代碼中有注釋。

class Solution {/*** 先看這里 先看這里 先看這里 先看這里* 看官方的例子* 輸入: 12258* 輸出: 5* 解釋: 12258有5種不同的翻譯,分別是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"* 也就是數字搭配可以是一位,可以是兩位(兩位情況下要小于26),也就是0-25取值范圍*/public:int translateNum(int num) { //如果num小于10了,也就沒有得拆分了,只有一種情況,例如數字 5 ,只有 f 這個字母表示if (num < 10) {return 1;}//大于10的情況,就要分情況討論了int re = num % 100;if (re < 10) {//情況1.:128105 % 100 = 5,那么5這個數字和無法和0合體的。那么去掉他 (num / 10),繼續下一輪遞歸return translateNum(num / 10);} else if (re < 26) {//情況2.:12810 % 100 = 10 ,可以分成兩種情況進行討論,就是1281 和 128 進行下一輪的遞歸,也就是對10這兩位數選擇,可以選擇成為ba和k。兩種情況return translateNum(num / 10) + translateNum(num / 100);} else {//情況.:128 % 100 = 28,這種情況比26大,因為題目要求是字母,28明顯比z大了,所以不能像情況2哪樣進行拆分成兩個遞歸進行相加return translateNum(num / 10);}} };

?

?

解題思路:從棋盤的左上角開始拿格子里的禮物,并每次向右或者向下移動一格、直到到達棋盤的右下角。根據題目說明,易得某單元格只可能從上邊單元格或左邊單元格到達。

? ? ?

class Solution { public:int maxValue(vector<vector<int>>& grid) {int rows = grid.size(), columns = grid[0].size();vector<vector<int>> dp(rows, vector<int>(columns, 0));for(int i = 0; i < rows; i ++)for(int j = 0; j < columns; j++){int left = 0, up = 0;if( i > 0 )up = dp[i-1][j];if( j > 0 )left = dp[i][j-1];dp[i][j] = max(left, up) + grid[i][j];// f(i,j) = max[f(i,j?1),f(i?1,j)] + grid(i,j);}int result = dp[rows-1][columns-1];return result;} };

?

?

解題思路:以 abcabcbb 為例,找出從每一個字符開始的,不包含重復字符的最長子串,那么其中最長的那個字符串即為答案。對于示例一中的字符串,我們列舉出這些結果,其中括號中表示選中的字符以及最長的字符串:

以 (a)bcabcbb 開始的最長字符串為 (abc)abcbb; 以 a(b)cabcbb 開始的最長字符串為 a(bca)bcbb; 以 ab(c)abcbb 開始的最長字符串為 ab(cab)cbb; 以 abc(a)bcbb 開始的最長字符串為 abc(abc)bb; 以 abca(b)cbb 開始的最長字符串為 abca(bc)bb; 以 abcab(c)bb 開始的最長字符串為 abcab(cb)b; 以 abcabc(b)b 開始的最長字符串為 abcabc(b)b; 以 abcabcb(b) 開始的最長字符串為 abcabcb(b)。

若新添加的字符是括號中的序列所擁有的,則將開始的索引指向原序列字符的后一位,記錄相應的長度數值,然后再繼續往后尋找。

class Solution { public:int lengthOfLongestSubstring(string s) {int start = 0, end = 0, length = 0, maxlength = 0;int Ssize = s.size();while (end < Ssize){char tmpChar = s[end];for (int index = start; index < end; index++){if (tmpChar == s[index]){start = index + 1; // 若新添加的字符是括號中的序列所擁有的,則將開始的索引指向原序列字符的后一位length = end - start;break; // 不用更新最大值的原因是這種情況下,的length最多和原來相等}}end++;length++;maxlength = max(maxlength, length);}return maxlength;} };

?

?

解題思路:根據題意直接完成(但是力扣上超時,其他的方法能解決,但是不想花太多時間去看)。

class Solution { public:bool ugly(int n){while(n%2 == 0)n /= 2;while(n%3 == 0)n /= 3;while(n%5 == 0)n /= 5;return (n == 1)? true:false;}int nthUglyNumber(int index) {if(index <= 0)return 0;int number = 0;int uglynumber = 0;while(uglynumber < index){++number;if(ugly(number))++uglynumber;}return number;} };

?

?

解題思路:用一個數組記錄字符出現的情況,然后通過遍歷找到只出現一次的字符。

class Solution { public:char firstUniqChar(string s) {int size = s.size();int a[256];if(s == "")return ' ';for(int i = 0; i < 256; i++)a[i] = 0;const char* p1 = s.c_str();const char* p2 = p1;while(*(p1) != '\0'){a[*(p1)]++; p1++;}while(*p2 != '\0'){if(a[*p2] == 1){return *p2;}p2++;}return ' ';} };

?

?

解題思路:(1) 兩層循環(簡單,但是超時了)。(2) 用歸并排序的方法(一時半會兒沒看懂,先做個記錄吧)。

class Solution { public:int reversePairs(vector<int>& nums) {int count = 0;for(int i = 0; i < nums.size(); i++){for(int j = i+1; j < nums.size(); j++){if(nums[i] > nums[j])count++;}}return count;} };class Solution { public:int coun=0;int temp[50000];void merge(vector<int>&arr, int s, int e) {int mid = (s + e) / 2;int i = s;int j = mid + 1;int k = s;while ((i <= mid) && (j <= e)) {if (arr[i] <=arr[j]) {temp[k++] = arr[i++];}else if (arr[i] > arr[j]) {temp[k++] = arr[j++];coun += (mid - i + 1);}}while (i <= mid) {temp[k++] = arr[i++];}while (j <= e) {temp[k++] = arr[j++];}for (int i = s; i <= e; i++) {arr[i] = temp[i];}}void mergeSort(vector<int>&arr, int s, int e) {if (s >= e) {return;}int mid = (s + e) / 2;mergeSort(arr, s, mid);mergeSort(arr, mid + 1, e);merge(arr, s, e);}int reversePairs(vector<int>& data) {int n=data.size();if(n==0) return 0;int s=0;int e=n-1;mergeSort(data, s, e);return coun;} };

?

總結

以上是生活随笔為你收集整理的剑指 offer 编程题 C++ 版总结(中)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。