编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:
输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]
class Solution(object):
def reverseString(self, s):
n = len(s)
if n <= 1:
return
for i in range(n // 2):
s[i], s[n - i - 1] = s[n - i - 1], s[i]
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
思路: 这道题目最关键的一点就是要考虑整数溢出的问题,所以我用了c++编的这道题目(用python怪怪的)
比如: 12345反转,先设定一个sum = 0
12345/10:余数是5,sum = 0 + 5 = 5;(12345 - 5)/ 10 = 1234
1234/10:余数是4,sum = 5 * 10 + 4 = 54;(1234 - 4)/ 10 = 123
。。。
以此类推
踩坑: 为了让我方便想,我打算把所有的负数先弄成正数,最后乘(-1)
然而,悲催的事情发生了。要知道int的范围是[−2^31, 2^31 − 1],也就是说−2^31如果变成正数就溢出了,于是我就加了一个
if (x == 0x80000000) { return 0; }
当然在运算的时候我也加了一个判断的逻辑,如果溢出的话直接返回0;
class Solution {
public:
int reverse(int x) {
// int 是否溢出:if( num>0x7fffffff || num<(signed int)0x80000000)
// 判断是否是负数
int neg = 1;
if (x < 0){
if (x == 0x80000000){
return 0;
}
neg = -1;
x = -x;
}
// 计算反转后的整数
long long int num = 0;
while (x > 0){
int cur = x % 10;
if (num * 10 + cur > 0x7fffffff){
return 0;
}
num = num * 10 + cur;
x = (x - cur) / 10;
}
return num * neg;
但是效果不是特别好,看看官方解答是怎么做的吧?
class Solution {
public:
int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > INT_MAX/10 || (rev == INT_MAX / 10 && pop > 7)) return 0;
if (rev < INT_MIN/10 || (rev == INT_MIN / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
};
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
s = “leetcode”
返回 0.
s = “loveleetcode”,
返回 2.
注意事项:您可以假定该字符串只包含小写字母
。
思路:
开一个长度为26的字母表,所有的值都是n。扫描字符串。
如果当前字母对应字母表中的值是n(说明还没有遇到过这个字母),就把字母表的这位置的值变成这个字母现在的index;
如果对应的不是n(说明已经重复了),就把字母表的这位置的值变成n+1;
这样做的好处是,最后我们的字母表的最小值就是要求的索引
,因为重复的和没出现的要么是n+1要么是n~
class Solution(object):
def firstUniqChar(self, s):
n = len(s)
idx_array = [n for i in range(26)]
for i in range(n):
letter = ord(s[i]) - ord('a')
if idx_array[letter] == n:
idx_array[letter] = i
else:
idx_array[letter] = n + 1
min_idx = min(idx_array)
if min_idx >= n:
return -1
else:
return min_idx
注意:
char-‘a’ = 数字
ord()
函数请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: “42”
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。
示例 4:
输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
class Solution {
public:
int myAtoi(string str) {
int n = str.size();
int i = 0, neg = 1;
int sum = 0;
// 去掉刚开始的空格
while (i<n){
if (str[i] == ' ') i++;
else break;
}
// str是空的
if (i == n) return 0;
// 第一个非空的字符不是正负号,也不是数字,直接return
if (str[i] != '-' && str[i] != '+' && (str[i] < '0' || str[i] > '9')) return 0;
// 遇到正负号
if (str[i] == '-' || str[i] == '+'){
if (str[i] == '-') neg = -1;
i++;
}
// 算一下
for (int k=i; k<n; k++){
if (str[k] <= '9' && str[k] >= '0'){
int pop = str[k] - '0';
if (sum > INT_MAX/10 || (sum == INT_MAX/10 && pop > 7)) return INT_MAX;
if (sum < INT_MIN/10 || (sum == INT_MIN/10 && pop > 8)) return INT_MIN;
sum = sum * 10 + neg * pop;
}
else return sum;
}
return sum;
}
};
踩的坑:
INT_MIN, INT_MAX
: 这两个常量是内置的,不需要自己定义,定义完之后程序就出问题了。。。。pop < -8
要变成pop > 8
+-1
这样的例子编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
思路:纵向比较法
Leetcode
Lead
Lets只要每个string的字符 从idx=0的地方开始比对,如果所有的string在同一个idx的位置字符相等,就把这个字符加到前缀里,如果不等于,就可以停止比对了
那么这个idx的值有限定吗? 我在这里先加了一个计算的过程,它求得的是string的向量中最短的那个string的长度len_min,而这个前缀长度肯定是小于len_min的
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string res = "";
// 空的string向量
if (strs.size() == 0) return res;
// 求string数组中最短的string的长度
vector<int> str_lens;
for (int i=0; i<strs.size(); i++) str_lens.push_back(strs[i].size());
int len_min = *min_element(str_lens.begin(), str_lens.end());
// 从每个string的第一个字符开始检查
bool end_flag = false;
for (int i=0; i<len_min; i++){
char cur_ch = strs[0][i];
for (int j=1; j<strs.size(); j++){
if (strs[j][i] != cur_ch){
end_flag = true;
break;
}
}
if (end_flag) return res;
else res = res + cur_ch;
}
return res;
}
};
踩的坑:
min_element(str_lens.begin(), str_lens.end())
返回的是迭代器,前面记得加*报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1
11
21
1211
111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
示例 1:
输入: 1
输出: “1”
示例 2:
输入: 4
输出: “1211”
这个题目考查的是读题能力? 什么one 1 two 1 的 我们就叫这个函数“饶舌歌手”好了!hey, bro!!!
class Solution(object):
def countAndSay(self, n):
s = "1"
for i in range(1, n): # 从n=1开始报数 循环n-1次
pre_s = s
s = ""
# 找相同的块
pre_ss = pre_s[0] # n-1时候的string
pre_idx = 0
idx = 1
# 遍历
while (idx < len(pre_s)):
# 如果当前位置的数和前面的不同,需要更新output string
if (pre_s[idx] != pre_ss):
times = idx - pre_idx
s += (str(times) + pre_ss) # 让我们的饶舌歌手唱出:数字出现了几次, 数字的value
pre_idx = idx
pre_ss = pre_s[idx]
idx += 1
s += (str(len(pre_s) - pre_idx) + pre_ss)
return s
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
示例 1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:
输入: s = “rat”, t = “car”
输出: false
说明:
你可以假设字符串只包含小写字母。
进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
- 用字典
- 因为题目已经假设字符串中只有小写字母,所以可以开一个长度为26的数组来储存
(ps: 测试了一下第二种方法会更快一点~)
注意:一定要判断两个字符串长度是否相等!
# 第一种方法:用字典实现
class Solution(object):
def isAnagram(self, s, t):
if len(s) != len(t):
return False
dic = {}
for char in s: # 记录第一个字符串里面的字符出现的次数
if char in dic:
dic[char] += 1
else:
dic[char] = 1
for char in t: # 遍历第二个字符串
if (char not in dic) or dic[char] == 0:
return False
dic[char] -= 1
return True
# 第二种方法:用数组实现
class Solution(object):
def isAnagram(self, s, t):
if len(s) != len(t):
return False
letters = [0 for i in range(26)]
for ss in s:
letters[ord(ss)-ord('a')] += 1
for tt in t:
if letters[ord(tt)-ord('a')] == 0:
return False
else:
letters[ord(tt)-ord('a')] -= 1
return True
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = “hello”, needle = “ll”
输出: 2
示例 2:
输入: haystack = “aaaaa”, needle = “bba”
输出: -1
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
这是一个模式匹配的问题,典型的算法有KMF、BM、Sunday等。
自己想只能想到暴力的解法(就是两个没匹配后再重头开始匹配,这样做的缺点在于没有很好的利用已经匹配过的信息,重新匹配的时候,位置可以跳动的更大一点),还是站在巨人的肩膀上看世界会更加美丽一点~
mark一下相关的资料:
我的代码如下
class Solution(object):
def strStr(self, haystack, needle):
"""
给定一个 haystack 字符串和一个 needle 字符串
在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)
"""
if needle == "": # needle是空字符串, 返回0
return 0
next = self.GetNext(needle)
j = 0
for i in range(len(haystack)):
while (j > 0 and haystack[i] != needle[j]): # 当前j与i的字符没有得到匹配
j = next[j]
if haystack[i] == needle[j]: # 当前j与i的字符得到匹配
j += 1
if j == len(needle): # 找到匹配串
return i-j+1
return -1 # 不存在,返回-1
def GetNext(self, needle):
next = [0 for i in range(len(needle)+1)] # 初始化 next 数组,注意长度 = 字符串长度 + 1
j = 0
for i in range(1, len(needle)):
"""
如果 字符串i位置 != 字符串 next【i】位置:
递归地看
字符串i位置 和 字符串 next【next【i】】位置 是否匹配?
不是的话继续和next【next【next【i】】】比较....
"""
while (j>0 and needle[i] != needle[j]):
j = next[j]
if (needle[i] == needle[j]): # 如果 字符串i位置 = 字符串next【i】位置,说明最大相同前缀后缀长度 + 1
j += 1
next[i+1] = j
return next
用时还是比较多的,有时间再去实现一下BM算法吧
题目来源: https://leetcode-cn.com/explore/interview/card/top-interview-questions-easy/5/strings/