天天看點

leetcode-字元串-簡單-C-第一部分序号13序号14序号20序号38序号58序号67序号125序号344序号345序号383序号387序号392序号415序号434序号443序号520序号521序号541序号551序号557

文章目錄

  • 序号13
  • 序号14
  • 序号20
  • 序号38
  • 序号58
  • 序号67
  • 序号125
  • 序号344
  • 序号345
  • 序号383
  • 序号387
  • 序号392
  • 序号415
  • 序号434
  • 序号443
  • 序号520
  • 序号521
  • 序号541
  • 序号551
  • 序号557

序号13

leetcode-字元串-簡單-C-第一部分序号13序号14序号20序号38序号58序号67序号125序号344序号345序号383序号387序号392序号415序号434序号443序号520序号521序号541序号551序号557

解析:由後一個字母和前一個字母大小比較,決定前一個字母的正負

  1. 模拟

    存儲字母對應值,可以用數組儲存,也可以函數 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

題目:編寫一個函數來查找字元串數組中的最長公共字首。

如果不存在公共字首,傳回空字元串 “”。

解析:

  1. 模拟

    逐個比較所有字元串的字首

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

題目:給定一個隻包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字元串,判斷字元串是否有效。

解析:

  1. 現在的字元與棧頂的字元比較,比對則出棧,否則入棧目前的字元

    最後判斷棧是否為空

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

題目:

leetcode-字元串-簡單-C-第一部分序号13序号14序号20序号38序号58序号67序号125序号344序号345序号383序号387序号392序号415序号434序号443序号520序号521序号541序号551序号557

解析:

  1. 打表法

    最後的答案過于長,可以直接打表,最後判斷輸出

  2. 模拟

    按照要去生成數組

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 。

說明:一個單詞是指僅由字母組成、不包含任何空格字元的 最大子字元串。

解析:

  1. 模拟

    倒着周遊字元串,找單詞

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。

解析:

  1. 模拟加法
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

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

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

解析:

  1. 模拟

    先轉換為隻有字母和數字字元的字元串,并且都轉為小寫字母。再判斷回文

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 碼表中的可列印字元。

解析:

  1. 模拟

    交換頭尾字元即可

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

題目:編寫一個函數,以字元串作為輸入,反轉該字元串中的元音字母。

解析:

  1. 雙指針

    針對元音字母反轉,需要雙指針進行判斷再反轉

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。

(題目說明:為了不暴露贖金信字迹,要從雜志上搜尋各個需要的字母,組成單詞來表達意思。)

解析:

  1. 散列記錄

    在第二個字元串中找到所需字母及其數量即可,不需要順序

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. 散列記錄

    記錄每個字母出現的次數,找到次數為 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"不是)。

解析:

  1. 模拟

    隻要按順序找到所有字元就可以

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 庫, 也不能直接将輸入的字元串轉換為整數形式。

解析:

  1. 模拟

    注意字元串的指派即可

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

題目:統計字元串中的單詞個數,這裡的單詞指的是連續的不是空格的字元。

請注意,你可以假定字元串裡不包括任何不可列印的字元。

解析:

  1. 模拟

    尋找空格,計入單詞

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 整數類型)。

在完成原地修改輸入數組後,傳回數組的新長度。

解析:

  1. 雙指針

    讀、寫指針以及一個記錄起始讀的指針。先寫字元,再寫次數

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”。

否則,我們定義這個單詞沒有正确使用大寫字母。

解析:

  1. 模拟

    用數學翻譯題目,大寫字母出現 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. 邏輯分析

    若兩個相同,傳回 -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’(遲到),那麼這個學生會被獎賞。

你需要根據這個學生的出勤記錄判斷他是否會被獎賞。

解析:

  1. 模拟

    處理連續的 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

題目:給定一個字元串,你需要反轉字元串中每個單詞的字元順序,同時仍保留白格和單詞的初始順序。

解析:

  1. 模拟

    尋找空格,然後反轉單詞

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;
}
           

繼續閱讀