Leetcode 5.最长回文子串
题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母组成
C语言代码
char* longestPalindrome(char* s) {
int i, j, max = 0, re = 0;
int len = strlen(s);
for (i = 1; i < len; i++)//奇数回文
{
int left = i - 1;
int right = i + 1;
while(left >= 0 && right < len && s[left] == s[right])
{
left--;
right++;
}
if(max < (right - left - 1))
{
max = right - left - 1;
re = left + 1;
}
}
for(i = 1; i < len; i++)//偶数回文
{
int left = i-1;
int right = i;
while(left >= 0 && right < len && s[left] == s[right])
{
left--;
right++;
}
if(max < (right - left - 1))
{
max = right - left - 1;
re = left + 1;
}
}
if(max < 2)
{
s[1] = '\0';
return s;
}
s[re + max] = '\0';
return s + re;
}
思路解释
回文数列有奇数回文和偶数回文,所以我分两个循环分别进行寻找。
第一个for循环是奇数回文的查找,从下标 1 开始循环(因为left需要分布在下标 i 的左边),让left和right分别分布在下标 i 的左右,然后进入循环,判断left和right下标所代表的字符是否相同,并且left和right的下标是否超出整个字符串的范围(0 ~ len),以此决定是否结束循环。结束循环后,将left - right - 1的结果与容纳最长回文字符串长度的变量max的值比较,取最大值,变量re记录最长回文字符串的左下标left - 1。
偶数回文同上。
最后执行判断,如果max的值小于 2 ,返回字符串首字符;否则返回最长回文字符串。
Leetcode 704.二分查找
题目描述
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
- 你可以假设 nums 中的所有元素是不重复的。
- n 将在 [1, 10000]之间。
- nums 的每个元素都将在 [-9999, 9999] 之间。
C语言代码
int search(int* nums, int numsSize, int target) {
int left = 0;
int right = numsSize - 1;
while(left <= right)
{
int mid = (left + right) / 2;
if(nums[mid] > target)
{
right = mid - 1;
}
else if(nums[mid] < target)
{
left = mid+1;
}
else
{
return mid;
}
}
return -1;
}
解题思路
因为数组元素有序(升序),且没有重复元素,这道题适合用二分查找。
判断 left 是否不大于 right ,以此决定是否进入循环,mid 取 left 和 right 的中位数,判断数组该下标的值与 target 的关系,如果等于 target ,直接返回 mid ;如果小于 target ,left 移动至 mid 右边一位;如果大于 target ,right 移动至 mid 左一位。
当循环结束时还没有返回任何的值,则返回 -1 ,说明数组nums不存在与 target 相等的元素。
二分查找感悟
二分法查找在左右闭合区间和左闭右开区间的处理时不同的。
- 循环条件从 left <=right 改为 left<right ,因为 left == right 在 [left,right) 上没有意义。
- 当 nums[mid] > target 时,right = mid ,而不是 right = mid - 1;
优化:
int mid = (left + right) / 2; 可以改为 int mid = left + ((right - left) / 2); 或 int mid = left + ((right - left) >> 1); 改为 int middle = left + ((right - left) >> 1);
int mid = (left + right) / 2;如果碰到 left 和 right 都接近 int 类型的极限,可能会溢出
int middle = left + ((right - left) >> 1); 是比特操作,让2进制的数右移一位,相当于除以2。