文章目录
题目
解题思路与代码详情
【题1】917. 仅仅反转字母
917. 仅仅反转字母: 给你一个字符串 s ,根据下述规则反转字符串:
所有非英文字母保留在原有位置。
所有英文字母(小写或大写)位置反转。
返回反转后的 s 。
题目解析: 将所有英文字符前后位置反转,其中字符串中包含非英文字符,若遇非英文字符,则反转时顺位。
解题思路: 设置双指针分别表示前后字符的位置,若当前前后位置都为英文字符,则进行元素互换,若前后位置有任何一处为非英文字符,则顺位。
# python3
class Solution:
def reverseOnlyLetters(self, s: str) -> str:
n=len(s)
slist=list(s)
left,right=0,n-1
while left<right:
if (ord(slist[left])>=97 and ord(slist[left])<=122) or (ord(slist[left])>=65 and ord(slist[left])<=90):
if (ord(slist[right])>=97 and ord(slist[right])<=122) or (ord(slist[right])>=65 and ord(slist[right])<=90):
slist[left],slist[right]=slist[right],slist[left]
left+=1
right-=1
else:
right-=1
else:
left+=1
return "".join(slist)
//C
char * reverseOnlyLetters(char * s){
int n=strlen(s);
int left=0,right=n-1;
char temp;
while(left<right){
if((s[left]-'a'>=0&&s[left]-'a'<26)||(s[left]-'A'>=0&&s[left]-'A'<26)){
if((s[right]-'a'>=0&&s[right]-'a'<26)||(s[right]-'A'>=0&&s[right]-'A'<26)){
temp=s[left];
s[left]=s[right];
s[right]=temp;
left++;
right--;
}else{
right--;
}
}else{
left++;
}
}
return s;
}
【题2】167. 两数之和 II - 输入有序数组
167. 两数之和 II - 输入有序数组: 给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
题目解析: 找出一组数中加和为目标值的唯一
一对数。
解题思路: 设置前后位置双指针,判断加和与目标值的关系。
#python3
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
n=len(numbers)
left,right=0,n-1
ret=[0]*2
while left<right:
if numbers[left]+numbers[right]<target:
left+=1
elif numbers[left]+numbers[right]>target:
right-=1
else:
ret[0]=left+1
ret[1]=right+1
break
return ret
//C
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize){
*returnSize=2;
int* ret=(int*)malloc(sizeof(int)*2);
int left=0,right=numbersSize-1;
while(left<right){
if(numbers[left]+numbers[right]<target){
left++;
}else if(numbers[left]+numbers[right]>target){
right--;
}else{
ret[0]=left+1;
ret[1]=right+1;
break;
}
}
return ret;
free(ret);
}
【题3】165. 比较版本号
**165. 比较版本号:**给你两个版本号 version1 和 version2 ,请你比较它们。
版本号由一个或多个修订号组成,各修订号由一个 ‘.’ 连接。每个修订号由 多位数字 组成,可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号,下标从 0 开始,最左边的修订号下标为 0 ,下一个修订号下标为 1 ,以此类推。例如,2.5.33 和 0.1 都是有效的版本号。
比较版本号时,请按从左到右的顺序依次比较它们的修订号。比较修订号时,只需比较 忽略任何前导零后的整数值 。也就是说,修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号,则该修订号视为 0 。例如,版本 1.0 小于版本 1.1 ,因为它们下标为 0 的修订号相同,而下标为 1 的修订号分别为 0 和 1 ,0 < 1 。
返回规则如下:
如果 version1 > version2 返回 1,
如果 version1 < version2 返回 -1,
除此之外返回 0。
知识点涉及
zip()
函数是Python内置函数。可用于将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后由这些元组形成zip
类型的新对象。可用list()转换输出列表
若作为参数的对象长度不一致,则返回的对象长度与最短的那个作为参数的对象的长度一致
。
- 使用
*
号可将zip类型的对象解压,解压后的数据类型为元组类型。如
a=[1,2,3];
b=[4,5,6,7];
new=zip(a,b)
print('1.',new)
print('2.',type(new))
newlist=list(zip(a,b))
print('3.',newlist)
a1,b1=zip(*zip(a,b))
print('4.',a1)
print('4.',type(a1))
print('5.',b1)
'''
输出结果为:
2. <zip object at 0x0000013437AE9B00>
3. <class 'zip'>
4. [(1, 4), (2, 5), (3, 6)]
5. (1, 2, 3)
6. <class 'tuple'>
7. (4, 5, 6)
'''
zip_longest 函数
. 使用时需要导入itertools模块
,且使用的时候需要指定一个填充值fillvalue
。返回的对象类型为itertools.zip_longest
。返回的对象长度与最长的那个作为参数的对象的长度一致
。较短的对象遍历完毕后使用设置的fillvalue值与较长的对象的元素形成元组。若填充值fillvalue
不设定,则默认的填充值为None
举例
a=[1,2,3];
b=[4,5,6,7];
from itertools import zip_longest
newlongest1=zip_longest(a,b)
newlongest2=zip_longest(a,b,fillvalue=666)
print('1.',type(newlongest1))
newlongestlist1=list(newlongest1)
newlongestlist2=list(newlongest2)
print('2.',newlongestlist1)
print('3.',newlongestlist2)
'''
输出结果为:
9. <class 'itertools.zip_longest'>
10. [(1, 4), (2, 5), (3, 6), (None, 7)]
11. [(1, 4), (2, 5), (3, 6), (666, 7)]
'''
- 字符串类型的数据转换为
int
型整数
C 库函数
int atoi(const char *str)
(函数声明) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。
此函数包含在C标准库<stdlib.h>
中
该函数返回转换后的长整数,如果没有执行有效的转换,则返回零
。
栗子
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int val;
char str[20];
strcpy(str, "98993489");
val = atoi(str);
printf("字符串值 = %s, 整型值 = %d\n", str, val);
strcpy(str, "runoob.com");
val = atoi(str);
printf("字符串值 = %s, 整型值 = %d\n", str, val);
return(0);
}
/*
输出结果为:
字符串值 = 98993489, 整型值 = 98993489
字符串值 = runoob.com, 整型值 = 0
*/
- 将字符串按规定分隔符分解
C 库函数 char *strtok(char *str, const char *delim)
(函数声明)分解字符串 str 为一组字符串,delim 为分隔符。
此函数包含在C标准库<string.h>
中
该函数返回被分解的第一个子字符串
,如果没有可检索的字符串,则返回一个空指针。
栗子
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.runoob.com - website";
const char s[2] = "-";
char *token;
/* 获取第一个子字符串 */
token = strtok(str, s);
/* 继续获取其他的子字符串 */
while( token != NULL ) {
printf( "%s\n", token );
token = strtok(NULL, s);
}
return(0);
}
/*
输出结果为:
This is
www.runoob.com
website
*/
题目解析: 比较两个版本号的大小。
解题思路: 字符整型的转换。
#python3
class Solution:
def compareVersion(self, version1: str, version2: str) -> int:
listtuple=[ll for ll in zip_longest(version1.split('.'), version2.split('.'), fillvalue=0)]
for v1, v2 in listtuple:
#zip_longest具体可以用来对列表的一一对应,如果列表的长度不一致,则其会选择最长的那个列表,#并将没有的填充为None(这个可以自己传参时设置)
x, y = int(v1), int(v2)
if x != y:
return 1 if x > y else -1
return 0
int compareVersion(char * version1, char * version2){
int ver1[1000] = {0};
int ver2[1000] = {0};
int ver1_len = 0; int ver2_len = 0;
for (char* p = strtok(version1, "."); p != NULL; p = strtok(NULL, ".")) {
ver1[ver1_len] = atoi(p);
ver1_len++;
}
for (char* q = strtok(version2, "."); q != NULL; q = strtok(NULL, ".")) {
ver2[ver2_len] = atoi(q);
ver2_len++;
}
int max_len = fmax(ver1_len, ver2_len);
for (int i = 0; i < max_len; i++) {
if (ver1[i] < ver2[i]) {
return -1;
} else if (ver1[i] > ver2[i]) {
return 1;
}
}
return 0;
}
【题4】443. 压缩字符串
443. 压缩字符串: 给你一个字符数组 chars ,请使用下述算法压缩:
从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符 :
1.如果这一组长度为 1 ,则将字符追加到 s 中。
2.否则,需要向 s 追加字符,后跟这一组的长度。
压缩后得到的字符串 s 不应该直接返回 ,需要转储到字符数组 chars 中。需要注意的是,如果组长度为 10 或 10 以上,则在 chars 数组中会被拆分为多个字符。
请在 修改完输入数组后 ,返回该数组的新长度。
你必须设计并实现一个只使用常量额外空间的算法来解决此问题。
题目解析: 需要在原列表中记录原列表中出现的字符与字符出现次数,若出现次数为1,则仅记录出现的字符,若出现次数大于等于10,则将出现的次数分割成0-9之内的数字。
解题思路:
(1)分别设置表示写入,遍历位置,求算出现次数的指针write,left,right。
(2)每次新字母开始遍历的位置为left,从该位置开始遍历只要字母相同,就继续往下查找,直至字母不再相同,记录该字符出现的次数
(3)将字母以及出现的次数依次替换原列表中的元素
(4)若出现次数大于10,则需要将出现次数分割为0-9以内的数字。
class Solution:
def compress(self, chars: List[str]) -> int:
n=len(chars)
write=0
left=0
while left<n:
num=0
right=left
while right<n and chars[right]==chars[left]:
right+=1
num=right-left
chars[write]=chars[left]
write+=1
if num>1:
for c in str(num):
chars[write]=c
write+=1
left=right
return write
//C
void swap(char *a, char *b) {
char t = *a;
*a = *b, *b = t;
}
void reverse(char *a, char *b) {
while (a < b) {
swap(a++, --b);
}
}
int compress(char* chars, int charsSize){
int write=0;
int left=0;
int num;
while(left<charsSize){
num=0;
int right;
right=left;
while(right<charsSize && chars[right]==chars[left]){
right++;
}
num=right-left;
chars[write++]=chars[left];
left=right;
if(num>1){
int ancor=write;
while(num>0){
chars[write++]=num % 10 +'0';
num /= 10;
}
reverse(&chars[ancor], &chars[write]);
}
}
return write;
}
【题5】2000. 反转单词前缀
2000. 反转单词前缀: 给你一个下标从 0 开始的字符串 word 和一个字符 ch 。找出 ch 第一次出现的下标 i ,反转 word 中从下标 0 开始、直到下标 i 结束(含下标 i )的那段字符。如果 word 中不存在字符 ch ,则无需进行任何操作。
例如,如果 word = “abcdefd” 且 ch = “d” ,那么你应该 反转 从下标 0 开始、直到下标 3 结束(含下标 3 )。结果字符串将会是 “dcbaefd” 。
返回 **结果字符串 **
题目解析: 反转从下标0到目标元素位置的子字符串。
解题思路: 遍历查找目标元素记录位置,反转子字符串。
class Solution:
def reversePrefix(self, word: str, ch: str) -> str:
n=len(word)
index=0
for i in range(n):
if word[i]==ch:
index=i
break
return word[:index+1][::-1]+word[index+1:]
void swap(char *a,char *b){
char temp=*a;
*a=*b;
*b=temp;
}
char * reversePrefix(char * word, char ch){
int n=strlen(word);
int index=0;
for(int i=0;i<n;i++){
if(word[i]==ch){
index=i;
break;
}
}
int j=index;
int i=0;
while(i<j){
swap(&word[i],&word[j]);
i++;
j--;
}
return word;
}
【题6】917. 仅仅反转字母
917. 仅仅反转字母: 给你一个字符串 s ,根据下述规则反转字符串:
所有非英文字母保留在原有位置。
所有英文字母(小写或大写)位置反转。
返回反转后的 s 。
见【题1】
【题7】475. 供暖器
475. 供暖器: 冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
在加热器的加热半径范围内的每个房屋都可以获得供暖。
现在,给出位于一条水平线上的房屋 houses 和供暖器 heaters 的位置,请你找出并返回可以覆盖所有房屋的最小加热半径。
说明:所有供暖器都遵循你的半径标准,加热的半径也一样。
题目解析: 求供暖器与房间之间的距离,确定每个供暖器与每个房间之间的所有最小距离中的最大值。
解题思路: 此处使用了排序+二分排序。
(1)将所有供暖器的位置按升序顺序排序
(2)逐一将房间的位置作为目标值,在供暖器的位置数组中二分查找与该目标值最近的那个值。
(3)(2)中的所有值取最大值。
class Solution:
def findRadius(self, houses: List[int], heaters: List[int]) -> int:
heaters.sort()
nheaters=len(heaters)
nhouse=len(houses)
maxs=0
for i in range(nhouse):
ans=-1
left,right=0,nheaters-1
while left<=right:
mid=left+(right-left)//2
if heaters[mid]>houses[i]:
right=mid-1
else:
left=mid+1
ans=mid
if left>nheaters-1 or right>nheaters-1:
maxs=max(maxs,abs(houses[i]-heaters[ans]))
else:
maxs=max(maxs,min(abs(houses[i]-heaters[right]),abs(houses[i]-heaters[left])))
return maxs
//C
int cmp(const void* p1, const void*p2){
return *(int*)p1-*(int*)p2;
}
int findRadius(int* houses, int housesSize, int* heaters, int heatersSize){
qsort(heaters, heatersSize, sizeof(int),cmp);
int ret=0;
int i;
for(i=0;i<housesSize;++i){
int ans=-1;
int left=0, right=heatersSize-1;
int mid;
while(left<=right){
mid=left+(right-left)/2;
if(heaters[mid]>houses[i]){
right=mid-1;
}else{
left=mid+1;
ans=mid;
}
}
int x;
if(ans==heatersSize-1){
x=abs(houses[i]-heaters[ans]);
}else if(ans<0){
x=abs(houses[i]-heaters[left]);
}else{
x=fmin(abs(houses[i]-heaters[ans]),abs(houses[i]-heaters[ans+1]));
}
ret=fmax(ret,x);
}
return ret;
}
【题8】面试题 16.06. 最小差
面试题 16.06. 最小差: 给定两个整数数组
a
和b
,计算具有最小差绝对值的一对数值(每个数组中取一个值),并返回该对数值的差
题目解析: 求两个整数数组各个元素之间的绝对差值,确定所有绝对差值中的最小值。
解题思路: 此处使用了排序+双指针。
(1)将两个整数数组都按升序顺序排序
(2)逐一比较两个数组元素之间的大小关系,求算绝对差值最小值
class Solution:
def smallestDifference(self, a: List[int], b: List[int]) -> int:
b.sort()
na=len(a)
nb=len(b)
ret=2147483647
for i in range(na):
ans=-1
left,right=0,nb-1
while left<=right:
mid=left+(right-left)//2
if b[mid]>a[i]:
right=mid-1
else:
left=mid+1
ans=mid
if ans==nb-1:
x=abs(a[i]-b[ans])
else:
x=min(abs(a[i]-b[ans]),abs(a[i]-b[ans+1]))
ret=min(ret,x)
return ret
/*先排序,然后两数字互相逼近*/
/*先排序,然后两数字互相逼近*/
#define ABS_NUM(a) ((a) > 0 ? (a) : -(a))
#define MIN_NUM(a, b) ((a) > (b) ? (b) : (a))
/*
long long ABS_NUM(long long a){
return a>0?a:(-a);
}
long long MIN_NUM(long long a, long long b){
return a>b?b:a;
}*/
int cmp(const void *a, const void *b) {
//const int l = *(int *)a;
//const int r = *(int *)b;
//return l > r ? 1 : -1;
return *(int*)a>*(int*)b;
}
int smallestDifference(int* a, int aSize, int* b, int bSize){
//if (a == NULL || aSize == 0 || b == NULL || bSize == 0) {
//return 0;
//}
qsort(a, aSize, sizeof(int), cmp);
qsort(b, bSize, sizeof(int), cmp);
long long min = ABS_NUM((long long)(a[0] - b[0]));
int i = 0, j = 0;
while (i < aSize && j < bSize) {
if (a[i] > b[j]) {
min = MIN_NUM(min, ABS_NUM((long long)(a[i] - b[j])));
j++;
}else if (a[i] < b[j]) {
min = MIN_NUM(min, ABS_NUM((long long)(a[i] - b[j])));
i++;
}else {
return 0;
}
}
return min;
}
参考文献
- https://blog.youkuaiyun.com/WhereIsHeroFrom/article/details/124522256
- https://blog.youkuaiyun.com/WhereIsHeroFrom/article/details/125076627
- Python:解析zip函数和zip_longest函数
- python zip_longest如何使用
- C 库函数 - atoi()
- C 库函数 - strtok()