文章目錄
- 序号13
- 序号14
- 序号20
- 序号38
- 序号58
- 序号67
- 序号125
- 序号344
- 序号345
- 序号383
- 序号387
- 序号392
- 序号415
- 序号434
- 序号443
- 序号520
- 序号521
- 序号541
- 序号551
- 序号557
序号13
解析:由後一個字母和前一個字母大小比較,決定前一個字母的正負
-
模拟
存儲字母對應值,可以用數組儲存,也可以函數 switch 傳回
int romanToInt(char * s){
int value[150] = { 0 };
value['I'] = 1; value['V'] = 5; value['X'] = 10;
value['L'] = 50; value['C'] = 100; value['D'] = 500;
value['M'] = 1000;
int sum = 0;
int preNum = value[s[0]];
int num;
for (int i = 1; s[i] != '\0'; i++)
{
num = value[s[i]];
if (preNum < num)
sum -= preNum;
else
sum += preNum;
preNum = num;
}
sum += preNum; //最後一個字母直接加
return sum;
}
序号14
題目:編寫一個函數來查找字元串數組中的最長公共字首。
如果不存在公共字首,傳回空字元串 “”。
解析:
-
模拟
逐個比較所有字元串的字首
int isSame(char** strs, int strsSize, int pos)
{
for (int i = 0; i < strsSize - 1; i++)
{
if (strs[i][pos] != strs[i+1][pos])
return 0;
}
return 1;
}
char * longestCommonPrefix(char ** strs, int strsSize){
if (strsSize == 0)
return "";
int len = strlen(strs[0]);
char* ans = (char*)malloc(sizeof(char) * (len+1)); //還有一個\0
strcpy(ans, strs[0]); //最長字首肯定在其中
int cnt = 0;
for (int i = 0; i < len; i++)
{
if (isSame(strs, strsSize, i))
cnt++;
else
break;
}
ans[cnt] = '\0'; //截取字元串
return ans;
}
序号20
題目:給定一個隻包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字元串,判斷字元串是否有效。
解析:
-
棧
現在的字元與棧頂的字元比較,比對則出棧,否則入棧目前的字元
最後判斷棧是否為空
bool isValid(char * s){
if (s[0] == '\0')
return true;
char stack[100000]; //測試點沒這麼多... 也可以用鍊棧
stack[0] = s[0];
int top = 0;
char ch;
for (int i = 1; s[i] != '\0'; i++)
{
if (top == -1)
stack[++top] = s[i];
else
{
ch = stack[top];
if ((ch == '(' && s[i] == ')') || (ch == '[' && s[i] == ']')
|| (ch == '{' && s[i] == '}'))
top--;
else
stack[++top] = s[i];
}
}
if (top == -1)
return true;
else
return false;
}
序号38
題目:
解析:
-
打表法
最後的答案過于長,可以直接打表,最後判斷輸出
-
模拟
按照要去生成數組
char* countAndSay(int n) {
if (n == 1)
return "1";
char str[5000];
strcpy(str, countAndSay(n - 1));
int len = strlen(str);
char cnt[50];
static char ans[5000];
strcpy(ans, "");
for (int i = 0; i < len;)
{
int j = i + 1;
while (j < len && str[j] == str[i])
j++;
sprintf(cnt, "%d", j - i);
strcat(ans, cnt);
char ch[2] = { str[i], '\0' };
strcat(ans, ch);
i = j;
}
return ans;
}
序号58
題目:給定一個僅包含大小寫字母和空格 ’ ’ 的字元串 s,傳回其最後一個單詞的長度。如果字元串從左向右滾動顯示,那麼最後一個單詞就是最後出現的單詞。
如果不存在最後一個單詞,請傳回 0 。
說明:一個單詞是指僅由字母組成、不包含任何空格字元的 最大子字元串。
解析:
-
模拟
倒着周遊字元串,找單詞
int lengthOfLastWord(char* s) {
int len = strlen(s);
int cnt = 0;
for (int i = len - 1; i >= 0; --i)
{
while (i >= 0 && s[i] != ' ')
{
--i;
++cnt;
}
if (cnt != 0)
return cnt;
}
return 0;
}
序号67
題目:給定兩個二進制字元串,傳回他們的和(用二進制表示)。
輸入為非空字元串且隻包含數字 1 和 0。
解析:
- 模拟加法
char* addBinary(char* a, char* b) {
int lenA = strlen(a);
int lenB = strlen(b);
int longLen, shortLen;
char one[1000], two[1000];
if (lenA > lenB)
{
strcpy(one, a);
strcpy(two, b);
longLen = lenA;
shortLen = lenB;
}
else
{
strcpy(one, b);
strcpy(two, a);
longLen = lenB;
shortLen = lenA;
}
int carry = 0;
int temp, j;
for (int i = shortLen - 1; i >= 0; --i)
{
j = longLen - (shortLen - i);
temp = carry + two[i] - '0' + one[j] - '0';
carry = temp / 2;
one[j] = temp % 2 + '0';
}
for (j = j - 1; carry == 1 && j >= 0; --j)
{
temp = 1 + one[j] - '0';
carry = temp / 2;
one[j] = temp % 2 + '0';
}
char* ans = (char*)malloc(sizeof(char) * (longLen + 2));
if (carry == 1)
{
strcpy(ans, "1");
strcat(ans, one);
}
else
strcpy(ans, one);
return ans;
}
序号125
題目:給定一個字元串,驗證它是否是回文串,隻考慮字母和數字字元,可以忽略字母的大小寫。
說明:本題中,我們将空字元串定義為有效的回文串。
解析:
-
模拟
先轉換為隻有字母和數字字元的字元串,并且都轉為小寫字母。再判斷回文
bool isPalindrome(char* s) {
static char dest[1000000];
int len = 0;
for (int i = 0; s[i] != '\0'; ++i)
{
if (isdigit(s[i]))
dest[len++] = s[i];
else if (isalpha(s[i]))
dest[len++] = tolower(s[i]);
}
for (int i = 0; i < len/2; ++i)
{
if (dest[i] != dest[len - 1 - i])
return false;
}
return true;
}
注:開很大的數組,用 static
序号344
題目:編寫一個函數,其作用是将輸入的字元串反轉過來。輸入字元串以字元數組 char[] 的形式給出。
不要給另外的數組配置設定額外的空間,你必須原地修改輸入數組、使用 O(1) 的額外空間解決這一問題。
你可以假設數組中的所有字元都是 ASCII 碼表中的可列印字元。
解析:
-
模拟
交換頭尾字元即可
void reverseString(char* s, int sSize) {
char ch;
for (int i = 0; i < sSize / 2; ++i)
{
ch = s[i];
s[i] = s[sSize - 1 - i];
s[sSize - 1 - i] = ch;
}
}
序号345
題目:編寫一個函數,以字元串作為輸入,反轉該字元串中的元音字母。
解析:
-
雙指針
針對元音字母反轉,需要雙指針進行判斷再反轉
bool isYuan(char c)
{
switch (c)
{
case 'a':
case 'A':
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U':
return true;
}
return false;
}
char* reverseVowels(char* s) {
int len = strlen(s);
int i = 0;
int j = len - 1;
char ch;
while (i < j)
{
if (isYuan(s[i]) && isYuan(s[j]))
{
ch = s[i];
s[i] = s[j];
s[j] = ch;
++i;
--j;
}
else if (!isYuan(s[i]))
++i;
else
--j;
}
return s;
}
序号383
題目:給定一個贖金信 (ransom) 字元串和一個雜志(magazine)字元串,判斷第一個字元串ransom能不能由第二個字元串magazines裡面的字元構成。如果可以構成,傳回 true ;否則傳回 false。
(題目說明:為了不暴露贖金信字迹,要從雜志上搜尋各個需要的字母,組成單詞來表達意思。)
解析:
-
散列記錄
在第二個字元串中找到所需字母及其數量即可,不需要順序
bool canConstruct(char* ransomNote, char* magazine) {
int hash[128] = { 0 };
for (int i = 0; ransomNote[i] != '\0'; ++i)
hash[ransomNote[i]]++;
for (int i = 0; magazine[i] != '\0'; ++i)
{
if (hash[magazine[i]] != 0)
hash[magazine[i]]--;
}
for (int i = 0; i < 128; ++i)
{
if (hash[i] != 0)
return false;
}
return true;
}
序号387
題目:給定一個字元串,找到它的第一個不重複的字元,并傳回它的索引。如果不存在,則傳回 -1。
解析:
-
散列記錄
記錄每個字母出現的次數,找到次數為 1 的,直接傳回
int firstUniqChar(char* s) {
int hash[128] = { 0 };
for (int i = 0; s[i] != '\0'; ++i)
hash[s[i]]++;
for (int i = 0; s[i] != '\0'; ++i)
{
if (hash[s[i]] == 1)
return i;
}
return -1;
}
序号392
題目:給定字元串 s 和 t ,判斷 s 是否為 t 的子序列。
你可以認為 s 和 t 中僅包含英文小寫字母。字元串 t 可能會很長(長度 ~= 500,000),而 s 是個短字元串(長度 <=100)。
字元串的一個子序列是原始字元串删除一些(也可以不删除)字元而不改變剩餘字元相對位置形成的新字元串。(例如,"ace"是"abcde"的一個子序列,而"aec"不是)。
解析:
-
模拟
隻要按順序找到所有字元就可以
bool isSubsequence(char * s, char * t){
int len1 = strlen(s);
int len2 = strlen(t);
int i = 0;
int j = 0;
while (i < len1 && j < len2)
{
if (s[i] == t[j])
i++;
j++;
}
if (i == len1)
return true;
else
return false;
}
序号415
題目:給定兩個字元串形式的非負整數 num1 和num2 ,計算它們的和。
注意:
num1 和num2 的長度都小于 5100.
num1 和num2 都隻包含數字 0-9.
num1 和num2 都不包含任何前導零。
你不能使用任何內建 BigInteger 庫, 也不能直接将輸入的字元串轉換為整數形式。
解析:
-
模拟
注意字元串的指派即可
char* addStrings(char* num1, char* num2) {
char one[5102], two[5102];
int oneLen, twoLen;
if (strlen(num1) > strlen(num2))
{
strcpy(one, num1);
strcpy(two, num2);
oneLen = strlen(num1);
twoLen = strlen(num2);
}
else
{
strcpy(one, num2);
strcpy(two, num1);
oneLen = strlen(num2);
twoLen = strlen(num1);
}
int carry = 0;
int i = twoLen - 1;
int j = oneLen - 1;
int temp;
for (; i >= 0; --i,--j)
{
temp = one[j] - '0' + two[i] - '0' + carry;
carry = temp / 10;
one[j] = temp % 10 + '0';
}
for (; carry == 1 && j >= 0; --j)
{
temp = one[j] - '0' + 1;
carry = temp / 10;
one[j] = temp % 10 + '0';
}
char* ans = (char*)malloc(sizeof(char) * (oneLen + 2));
if (carry == 1)
{
strcpy(ans, "1");
strcat(ans, one);
return ans;
}
strcpy(ans, one);
return ans;
}
序号434
題目:統計字元串中的單詞個數,這裡的單詞指的是連續的不是空格的字元。
請注意,你可以假定字元串裡不包括任何不可列印的字元。
解析:
-
模拟
尋找空格,計入單詞
int countSegments(char* s) {
int cnt = 0;
int flag = 0;
for (int i = 0; s[i] != '\0'; ++i)
{
if (s[i] != ' ')
{
if (flag == 0)
{
cnt++;
flag = 1;
}
}
else
flag = 0;
}
return cnt;
}
序号443
題目:給定一組字元,使用原地算法将其壓縮。
壓縮後的長度必須始終小于或等于原數組長度。
數組的每個元素應該是長度為1 的字元(不是 int 整數類型)。
在完成原地修改輸入數組後,傳回數組的新長度。
解析:
-
雙指針
讀、寫指針以及一個記錄起始讀的指針。先寫字元,再寫次數
int compress(char* chars, int charsSize) {
int read, write, startRead;
read = write = startRead = 0;
for (; read < charsSize; ++read)
{
if (read + 1 == charsSize || chars[read] != chars[read + 1])
{
chars[write++] = chars[startRead];
if (read > startRead)
{
char temp[4] = "";
sprintf(temp, "%d", read - startRead + 1);
for (int i = 0; temp[i] != '\0'; ++i)
chars[write++] = temp[i];
}
startRead = read + 1;
}
}
return write;
}
序号520
題目:給定一個單詞,你需要判斷單詞的大寫使用是否正确。
我們定義,在以下情況時,單詞的大寫用法是正确的:
全部字母都是大寫,比如"USA"。
單詞中所有字母都不是大寫,比如"leetcode"。
如果單詞不隻含有一個字母,隻有首字母大寫, 比如 “Google”。
否則,我們定義這個單詞沒有正确使用大寫字母。
解析:
-
模拟
用數學翻譯題目,大寫字母出現 0 次、1次且是首字母、全部都是
bool detectCapitalUse(char * word){
int cntUp = 0;
int len = strlen(word);
for (int i = 0; i < len; ++i)
{
if (isupper(word[i]))
cntUp++;
}
if (cntUp == len || cntUp == 0 || (cntUp == 1 && isupper(word[0])))
return true;
else
return false;
}
序号521
題目:給定兩個字元串,你需要從這兩個字元串中找出最長的特殊序列。最長特殊序列定義如下:該序列為某字元串獨有的最長子序列(即不能是其他字元串的子序列)。
子序列可以通過删去字元串中的某些字元實作,但不能改變剩餘字元的相對順序。空序列為所有字元串的子序列,任何字元串為其自身的子序列。
輸入為兩個字元串,輸出最長特殊序列的長度。如果不存在,則傳回 -1。
解析:
-
邏輯分析
若兩個相同,傳回 -1
若長度相同且不同,則傳回長度
若長度不同,則傳回最長的那個,那個必不是另一個的子序列
int findLUSlength(char * a, char * b){
if (!strcmp(a, b))
return -1;
int lenA = strlen(a);
int lenB = strlen(b);
return lenA > lenB ? lenA : lenB;
}
序号541
題目:給定一個字元串和一個整數 k,你需要對從字元串開頭算起的每個 2k 個字元的前k個字元進行反轉。如果剩餘少于 k 個字元,則将剩餘的所有全部反轉。如果有小于 2k 但大于或等于 k 個字元,則反轉前 k 個字元,并将剩餘的字元保持原樣。
解析:
1.模拟
先反轉最大 k 個,然後前移 k 個位置
void Reverse(char *str, int left, int right)
{
int i = left;
int j = right;
while (i < j)
{
char temp = str[i];
str[i] = str[j];
str[j] = temp;
++i;
--j;
}
}
char * reverseStr(char * s, int k){
int len = strlen(s);
for (int i = 0; i < len;)
{
if (i + k < len)
Reverse(s, i, i + k - 1);
else
Reverse(s, i, len - 1);
i += 2*k;
}
return s;
}
序号551
題目:給定一個字元串來代表一個學生的出勤記錄,這個記錄僅包含以下三個字元:
‘A’ : Absent,缺勤
‘L’ : Late,遲到
‘P’ : Present,到場
如果一個學生的出勤記錄中不超過一個’A’(缺勤)并且不超過兩個連續的’L’(遲到),那麼這個學生會被獎賞。
你需要根據這個學生的出勤記錄判斷他是否會被獎賞。
解析:
-
模拟
處理連續的 L,目前是 L,計數 +1;不是,計數歸 0
bool checkRecord(char * s){
int cntA = 0;
int ctCntL = 0;
for (int i = 0; s[i] != '\0'; ++i)
{
if (s[i] == 'L')
{
++ctCntL;
if (ctCntL > 2)
return false;
}
else
{
if (s[i] == 'A')
++cntA;
ctCntL = 0;
}
}
if (cntA <= 1)
return true;
else
return false;
}
序号557
題目:給定一個字元串,你需要反轉字元串中每個單詞的字元順序,同時仍保留白格和單詞的初始順序。
解析:
-
模拟
尋找空格,然後反轉單詞
void Reverse(char* left, char* right)
{
while (left < right)
{
char temp = *left;
*left = *right;
*right = temp;
++left;
--right;
}
}
char* reverseWords(char* s) {
char* left = s;
char* right = strchr(s, ' ');
int len = strlen(s);
while (right)
{
Reverse(left, right - 1);
left = right + 1;
right = strchr(left, ' ');
}
Reverse(left, s + len - 1);
return s;
}