1.1 實現一個算法,肯定一個字符串的全部字符是否全都不一樣。假使不容許使用額外的數據結構,又該如何處理?ios
/* 假設字符集爲ASCII字符串,那麼字符串至多有256個字符,由於一旦大於256個則一定有兩個是相同的 */ #include<iostream> #include<string> using namespace std; bool isUniqueChars(string str){ if (str.size() > 256) return false; bool char_set[256]; for(int i = 0; i < str.size; ++i) { int val = str[i]; //獲取字符對應得ASCII碼 if (char_set[val]) //這個字符已經在字符串中出現 return false; char_set[val] = 1; } return true; } /* 假如輸入的字符只含有小寫字母a到z,則咱們只須要用一個int型變量 */ bool isUniqueChar2(string str) { int flag = 0; if (str.size() > 26) return false; for (int i = 0; i < 26; ++i) { int val = str[i] - 'a'; if (flag&(1 << val) > 0) return false; flag |= (1 << val); } return true; }
1.2 用C或C++實現void reverse(char* str)函數,即反轉一個null結尾的字符串。算法
/*假設原地反轉,不分配額外空間,下面爲C語言實現*/ #include<stdio.h> void reverse(char* str) { char* end = str; char* start = str; char tmp; if (str) { while (*end) ++end; } --end; /*回退一個字符,由於最後的字符爲null*/ /*從首尾開始交換*/ while (start < end) { tmp = *end; *end = *start; *start = tmp; ++start; --end; } }
1.3 給定兩個字符串,請編寫程序,肯定其中一個字符串的字符從新排列後,可否變成另一個字符串。數組
/*給定兩個字符串,請編寫程序,肯定其中一個字符串的字符從新排列後,可否變成另一個字符串。*/ /*假設字符區分大小寫,空白字符也考慮在內,如下是兩種解法,使用C++*/ #include<iostream> #include<string> #include <algorithm> using namespace std; /*解法一:排序字符串,將兩個字符串進行排序後再進行比較*/ bool permutation1(string s, string t) { if (s.size() != t.size()) return false; string s1 = s; string t1 = t; /*進行排序*/ sort(s1.begin(), s1.end()); sort(t1.begin(), t1.end()); if (s1 == t1) return true; return false; } /*解法二:比較兩個字符串各字符數是否相同*/ bool permutation2(string s, string t) { if (s.size() != t.size()) return false; int count[256] = { 0 }; /*計算s中各個字符出現的次數*/ for (string::size_type i = 0; i !=s.size(); ++i) { int val = (int)s[i]; count[val]++; } for (string::size_type j = 0; j != t.size(); ++j) { int c = (int) t[j]; if (--count[c] < 0) return false; } return true; }
1.4 編寫一個方法,將字符串中的空格所有替換成「%20」。假定該字符串尾部有足夠的空間存放新增字符,而且知道字符串的真實長度。例如,輸入:"Mr Jone Smith",輸出:「Mr20%Jone20%Smith」。數據結構
/*編寫一個方法,將字符串中的空格所有替換成「%20」。假定該字符串尾部有足夠的空間存放新增字符,而且知道字符串的真實長度。*/ /*例如,輸入:"Mr Jone Smith",輸出:「Mr20%Jone20%Smith」。*/ #include<iostream> #include<string> using namespace std; void replaceSpaces(char* str,int length) { int spaceCount = 0; for (int i = 0; i < length; ++i) { if (str[i] == ' ') ++spaceCount; } int newLength = length + spaceCount * 2; str[newLength] = '\0'; int p = length - 1; int q = newLength - 1; while (p < q) { if (str[p] != ' ') str[q--] = str[p--]; else { str[q--] = '0'; str[q--] = '2'; str[q--] = '%'; p--; } } }
1.5 利用字符重複出現的次數,編寫一個方法,實現基本的字符串壓縮功能。好比,字符串"aabcccccaaa"會變成「a2b1c5a3」。若「壓縮」後字符串沒有變短,則返回原先的字符串。函數
#include<iostream> #include<string> using namespace std; string compress(string str) { if (str.empty()) return NULL; string str1; char last = str[0]; int count = 1; for (string::size_type i = 1; i < str.size(); ++i) { if (str[i] == last) ++count; else { str1.push_back(last); str1+=to_string(count); last = str[i]; count = 1; } } /*由於最後一組重複字符還未放入壓縮字符串中就退出循環,因此還要更新最後一組字符*/ str1.push_back(last); str1+=to_string(count); return str1.size() < str.size() ? str1: str; }
1.6 給定一幅由M*N矩陣表示的圖像,其中每一個像素的大小爲4字節,編寫一個方法,將圖像旋轉90度。不佔用額外內存空間可否作到?spa
/*假設順時針旋轉,*/ #include<iostream> using namespace std; void rotate(int** matrix, int n) { for (int layer = 0; layer < n / 2; ++layer) { int first = layer; int last = n - 1 - layer; for (int i = first; i < last; ++i) { int offset = i - first; //存儲上邊 int top = matrix[first][i]; //左到上 matrix[first][i] = matrix[last - offset][first]; //下到左 matrix[last - offset][first] = matrix[last][last - offset]; //右到下 matrix[last][last - offset] = matrix[i][last]; //上到右 matrix[i][last = top; } } }
1.7 編寫一個算法,若M*N的矩陣中某個元素爲0,則將其所在的行與列清零。指針
void setZeros(vector<vector<int> > matrix) { bool *row= new bool[matrix.size()]; bool *column= new bool[matrix[0].size()]; //爲保險起見首先初始化爲false for (int i = 0; i < matrix.size(); ++i) { for (int j = 0; j < matrix[0].size(); ++j) { row[i] = false; column[j] = false; } } //記錄值爲0的元素所在的行的索引和列的索引 for (int i = 0; i < matrix.size(); ++i) { for (int j = 0; j < matrix[0].size(); ++j) { if (matrix[i][j] == 0) { row[i] = true; column[j] = true; } } } //若行i或列j有個元素爲0,則matrix[i][j]置爲0 for (int i = 0; i < matrix.size(); ++i) { for (int j = 0; j < matrix[0].size(); ++j) { if(row[i]||column[j]) matrix[i][j] = 0; } } }
1.8 假定有一個方法isSubstring,可檢查一個單詞是否爲其餘字符串的子串。給定兩個字符串s1和s2,請編寫代碼檢查s2是否爲s1旋轉而成,要求只能調用一次isSubstring。(好比,waterbottle是erbottlewat旋轉後的字符串)code
/* *假設s2由s1旋轉而成,那麼咱們能夠找出旋轉點在哪。例如,若以wat旋轉waterbottle,就會獲得erbottlewat。 *咱們把字符串s1切分爲兩部分x和y,並將它們從新組合成s2. *s1=xy=waterbottle *x=wat *yerbottle *s2=yx=erbottlewat *咱們須要確認的是有沒有辦法將s1切分紅xy=s1,yx=s2。不論xy的分割點在何處,xy都是xyxy的子串。也即s2是s1s1的子串 */ #include<iostream> using namespace std; bool isRotation(string s1, string s2) { int len = s1.size(); //檢查s1和s2是否等長且不爲空 if (len == s1.size() && len > 0) { //憑藉s1和s1,放入新字符串中 string s1s1 = s1 + s1; return isSubstring(s1s1, s2); } return false; }
2.1 編寫代碼,移除爲排序鏈表中的重複節點。進階:若是不得使用臨時緩衝區,該怎麼解決?blog
#include<iostream> #include<map> using namespace std; //鏈表節點定義 struct Node { Node* next = NULL; int data; }; /*解法一:採用散列表來存儲節點的值是否出現過,若重複,則刪除該節點。*/ void deleteDups1(Node *phead) { map<int, bool> imap; Node* previous = phead; Node* p = phead; while (p != NULL) { if (imap[p->data]) { previous->next =p->next; } else { imap[p->data] = true; previous = p; } p = p->next; } } /*解法二:進階不使用額外緩衝區,使用兩個指針來迭代:current迭代訪問整個列表,runner用於檢查後續的節點是否重複*/ void deleteDups2(Node* phead) { if (phead == NULL) return; Node* current = phead; while (current != NULL) { Node* runner = current; while (runner->next != NULL) { if (current->data == runner->next->data) { current->next = runner->next->next; } else { runner = runner->next; } current = current->next; } } }