【每日刷题】Day104
🥕个人主页:开敲🍉
🔥所属专栏:每日刷题🍍
🌼文章目录🌼
1. 3. 无重复字符的最长子串 - 力扣(LeetCode)
2. 1004. 最大连续1的个数 III - 力扣(LeetCode)
3. 704. 二分查找 - 力扣(LeetCode)
1. 3. 无重复字符的最长子串 - 力扣(LeetCode)
//解法一:暴力枚举+哈希表。
//暴力遍历所有的子数组,记录最长子数组的长度
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int ans = 0;
for(int i = 0;i<s.size();i++)
{
int hash[128] = {0};
int j = i;
//利用哈希表判断字符是否重复出现
while(j<s.size()&&!hash[s[j]])
{
hash[s[j]] = 1;
j++;
}
//记录最大子数组长度
ans = ans>(j-i)?ans:(j-i);
}
return ans;
}
};
//解法二:滑动窗口+哈希表。
//解法二是在解法一的基础上进行优化的:
class Solution {
public:
int lengthOfLongestSubstring(string s)
{
int ans = 0;
int i = 0;
int j = 0;
int hash[128] = {0};
while(j<s.size())
{
//判断是否为重复字符
//如果不是:
if(!hash[s[j]])
{
//将该字符放入哈希表
hash[s[j]] = 1;
j++;
//更新最长子数组长度
ans = ans>(j-i)?ans:(j-i);
}
//如果是
else
{
//将i跳到与j相同字符的下一个位置,再将j++
while(s[i]!=s[j])
{
hash[s[i]] = 0;
i++;
}
i++;
j++;
}
}
return ans;
}
};
2. 1004. 最大连续1的个数 III - 力扣(LeetCode)
//解法一:暴力枚举+计数器
//暴力枚举每一个 0的个数不超过k 的子区间,记录最大子区间长度
class Solution {
public:
int longestOnes(vector<int>& nums, int k)
{
int ans = 0,i = 0,j = 0,tmp = k;
while(j<nums.size())
{
//如果值为1,继续向后遍历
if(nums[j])
j++;
else
{
//如果值为0,判断是否还能够翻转0,如果可以,则消耗一次翻转次数,向后遍历
if(tmp)
{
j++;
tmp--;
}
//如果翻转次数耗尽,则重置翻转次数,记录最大长度,i++,j = i 进入下一个区间继续枚举
else
{
tmp = k;
ans = ans>(j-i)?ans:(j-i);
i++;
j = i;
}
}
}
ans = ans>(j-i)?ans:(j-i);
return ans;
}
};
//解法二:滑动窗口+计数器
//解法二也是在解法一的基础上面优化出来的:
class Solution {
public:
int longestOnes(vector<int>& nums, int k)
{
int ans = 0,i = 0,j = 0,zero = 0;
while(j<nums.size())
{
//如果值为1,j继续向后遍历
if(nums[j])
j++;
else
{
//否则,如果zero计数器<=k,则zer++,再次判断zero是否<=k,如果依然<=k,则让j向后遍历
if(zero<=k)
{
zero++;
if(zero<=k)
j++;
}
//如果zero>k,记录最大长度,将i遍历到合法的区间内
else
{
ans = ans>(j-i)?ans:(j-i);
while(zero>k)
{
if(!nums[i])
zero--;
i++;
}
j++;
}
}
}
ans = ans>(j-i)?ans:(j-i);
return ans;
}
};
3. 704. 二分查找 - 力扣(LeetCode)
//思路:二分查找的实现。
//定义left、right和mid三个指针,left指向首元素right指向尾元素,mid指向left和right形成区间的中间的元素。
//如果mid指向元素 < target,让left = mid + 1 缩小区间
//如果mid指向元素 > target,让right = mid - 1 缩小区间
//如果mid指向元素 == target 返回mid
//如果循环结束,mid指向元素 != target,返回-1
class Solution {
public:
int search(vector<int>& nums, int target)
{
int left = 0;
int right = nums.size()-1;
int mid;
while(left<=right)
{
//mid指向left和right形成区间的中间的元素
mid = (left+right)/2;
//缩小区间
if(nums[mid]<target)
left = mid+1;
else if(nums[mid]>target)
right = mid-1;
//找到target,返回mid
else
return mid;
}
//循环结束说明没找到target,返回-1
return -1;
}
};