小奥的学习笔记

  • Home
  • Learning & Working
    • Speech Enhancement Notes
    • Programming language
    • Computer & DL
    • MOOC
  • Life
    • Life Time
    • Thinking & Comprehension
    • Volunteer
    • Plan
    • Travel
  • Footprints
  • GuestBook
  • About
    • About Me
    • 个人履历
    • 隐私策略
  1. 首页
  2. Study-notes
  3. Programming language
  4. Algorithm
  5. Leetcode
  6. 正文

Leetcode题目解析(191119):136&137&139

2019年11月19日 877点热度 0人点赞 0条评论

Leetcode 136:只出现一次的数字

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例

输入: [2,2,1]
输出: 1

解题思路

这里我们可以利用异或的原理,我们发现在异或中:

a⊕0=a;a⊕a=0。a⊕b⊕a=(a⊕a)⊕b=0⊕b=b

所以我们只需要将所有的数进行 XOR 操作,得到那个唯一的数字。

代码实现

int singleNumber(vector<int>& nums) {
    //if (nums.empty())
    //  return 0;
    for (int i = 1; i < nums.size(); i++)
        nums[0] ^= nums[i];//异或
    return nums[0];
}

复杂度

运行时间

时间复杂度:O(n),空间复杂度:没有使用额外的空间。

拓展:Leetcode137(只出现一次的数字2)

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。你的算法应该具有线性时间复杂度。 你不可使用额外空间来实现。

解题思路

我们前面的基础上用到了“异或”,它本质上是一种二进制下不考虑进位的加法。所以对于本题,我们可以考虑构造一种三进制下不考虑进位的加法,这种方法存在以下运算规则:假设运算符号为@,则0@1=1,1#1=2,2#1=0。所以在这种运算规则之下,出现3次的数字全部抵消为0,而只留下只出现1次的数字。
所以有以下步骤:
* ones^=num:记录至目前元素num,二进制某位出现1次(当某位出现3次时有ones=1,与twos=1共同表示“出现3次”)。
* twos|=ones&num:记录至目前元素num,二进制某位出现2次(当某位出现2次时,twos=1且ones=0)
* threes=ones&twos:记录至目前元素num,二进制某位出现3次(即当ones和twos对应位同时为1时three=1)。
one&=~threes,two&=~threes:将onestwos中出现了3次的对应位清零,实现“不考虑进位的三进制加法”。

进一步简化:
以上过程本质上是通过构建3个变量的状态转换表来表示对应位的出现次数:使所有数字“相加”后出现3N+1次的位ones=1,出现3N,3N+2次的位为ones=0。由于three其实是ones&twos的结果,因此我们可以舍弃threes,仅使用ones和twos来记录出现次数。

解析转载自:
https://leetcode-cn.com/problems/single-number-ii/solution/single-number-ii-mo-ni-san-jin-zhi-fa-by-jin407891/

代码实现

int singleNumber(vector<int>& nums) {
    //if (nums.empty())
    //  return 0;
    int ones = 0, twos = 0;
    for (int num : nums) {
        ones = ones ^ num & ~twos;
        twos = twos ^ num & ~ones;
    }
    return ones;
}

复杂度分析

运行时间
时间复杂度 O(n):遍历一遍 nums 需要线性时间复杂度;
空间复杂度 O(1):使用常数额外空间。

Leetcode 139:单词拆分

题目描述

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。

示例

示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
注意你可以重复使用字典中的单词。

示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

解题说明

这个题可以想到可以用动态规划的思想。原因是这个问题可以将给定的字符串s分解为s1和s2,然后这两个是独立的问题,同时s1和s2又可以继续拆分下去。所以说这符合动态规划的条件。

我们可以考虑如何进行动态规划求解。既然是分成两个字符串,实际上就是用两个指针i和j,其中i是当前字符串从头开始的子字符串的长度,j是当前字符串的拆分位置,于是字符串就被拆分为了(0,j)和(j+1,i)的区间。然后设置一个一维dp数组,dp数组中的下标代表着字符串结束的下标。

我们在求dp的时候,首先初始化dp[0]=true,剩余元素都初始化为false。我们用下标i来考虑所有从当前字符串开始的可能的字符串。对于每一个字符串,我们用j将它们分解为s1和s2,也就是说只有s1和s2都为true才可以,所以等价于,如果想要求dp[i],就要看dp[j](dp[j]代表到字符串下标到j的这个子字符串是否是子串,也就是s1是否是子串)和s2的情况。我们首先看dp[j]是否为true,若是则检查s2,s2实际上是下标(j+1,i),所以只需要执行find(wordDict.begin(), wordDict.end(), s.substr(j, i - j)) != wordDict.end()即可。这样就完成了整个判断操作。最后返回dp[len]就好了。

代码实现

bool wordBreak(string s, vector<string>& wordDict) {
    int len = s.size();
    if (len == 0 || wordDict.size() == 0)
        return false;
    vector<bool> dp(len + 1, false);
    dp[0] = true;
    for (int i = 1; i <= len; i++)
    {
        for (int j = i - 1; j >= 0; j--) {
            if (dp[j] && find(wordDict.begin(), wordDict.end(), s.substr(j, i - j)) != wordDict.end())
            {
                dp[i] = true;
                break;
            }
        }
    }
    return dp[len];
}

复杂度

时间复杂度:O(n2),因为两层for循环。
空间复杂度:O(n),因为使用了长度为n+1的dp数组。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: leetcode
最后更新:2019年11月19日

davidcheung

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

搜索
欢迎关注我的个人公众号
最新 热点 随机
最新 热点 随机
DEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架 奥地利匈牙利九日游旅程 论文阅读之Study of the General Kalman Filter for Echo Cancellation 小奥看房之鸿荣源珈誉府 杭州往返旅途及西溪喜来登和万怡的体验报告 2022年的第一篇碎碎念
奥地利匈牙利九日游旅程论文阅读之Study of the General Kalman Filter for Echo CancellationDEEPFILTERNET:一种基于深度滤波的全频带音频低复杂度语音增强框架
我的清明节假期 C++面向对象程序设计课程笔记(第八周) 美军进攻莱芜,大败而归 决定还是用这个风格吧 某些字幕组的某些人,注意! 未知原因,导致数据库部分数据丢失
标签聚合
生活 Java python学习 高中 Python 鸟哥的linux私房菜 学习 算法 leetcode linux
最近评论
davidcheung 发布于 5 个月前(02月09日) The problem has been fixed. May I ask if you can s...
tk88 发布于 5 个月前(02月07日) Hmm is anyone else having problems with the pictur...
cuicui 发布于 9 个月前(10月20日) :wink:
niming 发布于 10 个月前(09月19日) 同级校友,能刷到太巧了
davidcheung 发布于 2 年前(08月16日) 我得找一下我之前整理的word文档看一下,如果找到了我就更新一下这篇文章。
Nolan 发布于 2 年前(07月25日) 您的笔记非常有帮助。贴图不显示了,可以更新一下吗?
davidcheung 发布于 3 年前(06月19日) 到没有看webrtc的代码。现在主要在看我们公司的代码了。。。只是偶尔看一看webrtc的东西。。。
aobai 发布于 3 年前(03月13日) gain_change_hangover_ 应该是每三个block 只能够调整一次,这样保证每帧...
匿名 发布于 5 年前(12月30日) 烫
小奥 发布于 5 年前(12月12日) webRTC里面的NS本身我记得就是在C++里面呀

COPYRIGHT © 2025 小奥的学习笔记. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

陕ICP备19003234号-1

鲁公网安备37120202000100号