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