每日练习——leetcode3和11

目录

3. 无重复字符的最长子串

题目描述

解题思路

代码实现

11. 盛最多水的容器

题目描述

解题思路

代码实现


3. 无重复字符的最长子串

题目描述

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

解题思路

使用滑动窗口的算法,并结合哈希表来快速判断某个字符是否已被访问过。

1.初始化:

获取字符串s的长度len。如果字符串为空(len == 0),则最长无重复字符子串的长度显然为0,直接返回0。

定义左指针left和右指针right,都初始化为0。这两个指针用于定义当前考虑的子串范围。定义maxLen用于记录当前找到的最长无重复字符子串的长度,初始化为0。

定义哈希表hash,大小为256,并全部初始化为0。哈希表的索引对应字符的ASCII值,值对应字符的访问状态(0表示未访问,1表示已访问)。

2.遍历字符串

使用while循环遍历字符串,直到右指针right达到字符串的末尾。

3.检查字符状态

在每次循环中,检查当前右指针right指向的字符s[right]的访问状态:

如果hash[s[right]]为0,表示该字符在当前考虑的子串中还未出现过:将hash[s[right]]设置为1,标记该字符为已访问。更新maxLen为当前子串长度(right - left + 1)和maxLen中的较大值。右指针right右移一位,继续考虑下一个字符。

如果hash[s[right]]为1,表示该字符在当前考虑的子串中已经出现过:为了找到最长无重复字符子串,需要移动左指针left,并重置左指针及其左侧所有字符的访问状态(在hash中对应位置设置为0)。左指针left右移一位。

4.返回结果

当遍历完整个字符串后,maxLen中保存的就是最长无重复字符子串的长度,将其作为结果返回。

代码实现

int lengthOfLongestSubstring(char* s) {
    int len = strlen(s);
    if (len == 0)
        return 0;
    int left = 0, right = 0;
    int maxLen = 0;
    int hash[256] = {0};
    while (right < len) {
        // 如果当前字符没有被访问过
        if (hash[s[right]] == 0) {
            hash[s[right]] = 1; // 标记当前字符为已访问
            maxLen = (right - left + 1) > maxLen ? (right - left + 1): maxLen; // 更新最大长度
            right++;                                       // 右指针右移
        } else {
            // 如果当前字符已经被访问过,则移动左指针,并重置左指针及其左侧所有字符的访问状态
            hash[s[left]] = 0;
            left++;
        }
    }
    return maxLen;
}

11. 盛最多水的容器

题目描述

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

示例 1:

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例 2:

输入:height = [1,1]
输出:1

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

解题思路

这个问题是关于找出两条垂线,使得它们与x轴共同构成的容器可以容纳最多的水。一个直观的想法是遍历所有可能的线对,并计算它们之间形成的容器的面积,然后找出面积最大的那个。但是,这种方法的时间复杂度是O(n^2),对于较大的n,效率较低。

为了优化这个问题,可以使用双指针法。其基本思想是,初始化两个指针分别指向数组的开始和结束,然后逐步向中间移动,同时更新最大面积。

具体步骤如下:

1.初始化两个指针,left指向数组的第一个元素,right指向数组的最后一个元素。同时初始化最大面积max为0。

2.进入循环,当left < right时执行以下操作:

计算当前left和right所指向的两条线构成的容器的面积s,面积的计算公式为s = min(height[left], height[right]) * (right - left)。如果s大于max,则更新max为s。

3.移动指针:比较height[left]和height[right],如果height[left]较小,则left右移一位;如果height[right]较小,则right左移一位。

4.返回结果:循环结束后,max中保存的就是最大的容器面积,返回max即可。

为什么这种方法是有效的呢?因为容器的面积取决于两个因素:两条线的高度和它们之间的距离。在移动指针的过程中,始终保持着一条高度较高的线不动,而移动高度较低的线。这样做的目的是尽可能地保留高度较高的线,因为移动高度较高的线可能导致面积变小。同时,通过缩小搜索范围,减少了计算量,从而提高了效率。

这种双指针法的时间复杂度是O(n),因为每个指针最多移动n次。因此,对于较大的n,这种方法比遍历所有线对的方法更加高效。

代码实现

int maxArea(int* height, int heightSize) {
    int s = 0, max = 0, left = 0, right = heightSize - 1;
    while (left < right) {
        if (height[left] > height[right]) {
            s = height[right] * (right - left);
            if (s > max)
                max = s;
            right--;
        } else {
            s = height[left] * (right - left);
            if (s > max)
                max = s;
            left++;
        }
    }
    return max;
}

  • 37
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值