力扣 58最后一个单词的长度

文章讨论了两种不同的JavaScript函数实现,旨在找出字符串中最后一个单词的长度。第一种方法使用for循环,较为繁琐,而第二种方法利用while循环,实现更简洁。两者时间复杂度相同,但第二种方法在代码清晰度和效率上更优。

最近感觉自己代码到处都是逻辑漏洞,为了可持续发展(为了钱途,记录一些算法学习与对比实现

//我的笨办法
  var lengthOfLastWord = function (s){
    let i=0;
    for(let index=s.length-1;index>=0;index--){
      if(s[index] != ' '){//不等于空 
        i++;
        if(s[index-1]==' '||s[index-1]=='undefined'){
          break;
        }
      }
    }
    return i;
  }
  //实例办法
 var lengthOfLastWord = function(s) {
    let index = s.length - 1;
    while (s[index] === ' ') { //过滤字符串尾部空值
        index--;
    }
    let wordLength = 0;
    //不是空串且当前数有值,为true时一直执行
    while (index >= 0 && s[index] !== ' ') {
        wordLength++;//字符长度加一
        index--;
    }
    return wordLength;
};

之前没想过用while循环,


GPT大爹的评价:

这两个函数的目的都是求一个字符串中最后一个单词的长度。它们的实现思路不同,第一个函数是从字符串末尾往前遍历,直到找到第一个非空格的字符,然后继续往前遍历计算最后一个单词的长度。第二个函数是从字符串末尾往前遍历,跳过末尾的空格字符,找到最后一个单词的结束位置,然后计算它的长度。

两个函数的时间复杂度都是O(n),但是第一个函数的实现比较繁琐,需要使用多个判断条件,而第二个函数使用了while循环,并且只使用了两个变量,实现比较简洁清晰。因此,第二个函数的实现优于第一个函数。

<think> 我们正在处理力扣58题(最后一个单词长度)的C++代码问题。 题目描述:给定一个字符串 s,由若干单词组成,单词之间用空格隔开。返回字符串中最后一个单词长度。如果不存在最后一个单词,请返回 0 。 官方C++代码可能类似于: int lengthOfLastWord(string s) { int index = s.size() - 1; while (index >= 0 && s[index] == ' ') { index--; // 跳过末尾空格 } int end = index; // 此时end指向最后一个单词最后一个字符 while (index >= 0 && s[index] != ' ') { index--; // 跳过最后一个单词 } return end - index; } 用户问题聚焦在第二个while循环的条件:`while (index >= 0 && s[index] != ' ')` 如果调换两个条件的顺序,变成:`while (s[index] != ' ' && index >= 0)` 那么在测试用例为"a"(即字符串仅有一个字母)时会出现问题。 原因分析: 调换顺序后,当index为-1时,我们会先判断`s[index] != ' '`,而`s[-1]`是无效的内存访问(数组越界),导致未定义行为(可能崩溃或得到错误结果)。 详细解释: 在原始代码中,条件`index >= 0`在前,当index减到-1时,由于短路求值,后面的条件`(s[index]!=' ')`不会被执行,因此不会出现越界访问。 而调换后,当index为-1时,由于要先判断`s[index]!=' '`,就会尝试访问`s[-1]`,这是非法访问,会导致程序崩溃或不可预知的行为。 以"a"为例(字符串s="a"): 第一步:跳过末尾空格(没有空格,所以index仍然是0)。 第二步:进入第二个while循环: 初始index=0,满足`s[0]!=' '`,所以index减1变为-1。 然后下一轮循环:先判断`s[-1]!=' '`,此时访问s[-1]就是越界。 因此,正确的顺序应该是先检查索引是否有效(index>=0),再访问数组元素。 总结:在循环条件中,涉及数组索引访问的条件必须放在索引有效性检查之后,以避免越界访问。 相关问题: 1. 短路求值(short-circuit evaluation)在编程中还有哪些应用场景? 2. 如何避免数组越界访问这类错误? 3. 在力扣58题中,除了边界条件,还有哪些需要注意的细节? </think> ### 问题分析 在力扣58 题(最后一个单词长度)的官方 C++ 代码中,关键逻辑是: ```cpp while (index >= 0 && s[index] != ' ') // 正确顺序 ``` 若调换条件顺序为: ```cpp while (s[index] != ' ' && index >= 0) // 错误顺序 ``` 则在输入字符串 `"a"` 时会出现**内存越界访问**,导致未定义行为(程序崩溃或错误结果)。原因如下: --- ### 根本原因:短路求值规则 C++ 的逻辑与操作 `&&` 遵循**短路求值**规则: - 若左侧表达式为 `false`,则右侧表达式**不会被执行**。 - 若左侧表达式为 `true`,则继续执行右侧表达式。 #### 错误顺序的执行流程(以 `"a"` 为例): 1. 初始化 `index = s.size()-1 = 0`(字符串 `"a"` 的最后一个字符下标为 `0`)。 2. 第一轮循环: - 先执行 `s[index] != ' '`:`s[0] = 'a'` 非空格 → 条件为 `true`。 - 再执行 `index >= 0`:`0 >= 0` → `true` → 进入循环体,`index--` 后变为 `-1`。 3. 第二轮循环: - **先执行 `s[index] != ' '`**:此时 `index = -1`,尝试访问 `s[-1]` → **非法内存访问**(数组越界)。 #### 正确顺序的执行流程: ```cpp while (index >= 0 && s[index] != ' ') // 左侧是索引检查 ``` - 当 `index = -1` 时,先执行 `index >= 0` → `false` → 右侧 `s[index] != ' '` **被跳过** → 循环终止,无越界访问。 --- ### 关键结论 1. **边界保护优先**:涉及数组/字符串索引的检查(如 `index >= 0`)必须置于逻辑与操作的**左侧**,利用短路规则避免非法访问。 2. **`"a"` 的特殊性**: - 字符串长度为 1,`index` 从 `0` 递减到 `-1` 只需一次循环。 - 错误顺序在第二次循环时直接访问 `s[-1]`,而正确顺序在 `index = -1` 时跳过右侧检查。 --- ### 相关问题 1. 短路求值在其他语言(如 Java/Python)中是否遵循相同规则? 2. 如何通过调试工具(如 Valgrind)检测此类内存越界问题? 3. 力扣58 题中,还有哪些边界用例需要特别注意(如空字符串或全空格字符串)?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值