移动应用开发实验室第一次考核题分析

大一上考核题

力扣125验证回文串

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。

示例 1:

输入: s = “A man, a plan, a canal: Panama”
输出:true
解释:“amanaplanacanalpanama” 是回文串。
示例 2:

输入:s = “race a car”
输出:false
解释:“raceacar” 不是回文串。
示例 3:

输入:s = " "
输出:true
解释:在移除非字母数字字符之后,s 是一个空字符串 “” 。
由于空字符串正着反着读都一样,所以是回文串。

题目分析

将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

解题思路

利用快慢指针遍历字符串,用isalnum函数判断字符串里是否是数字或字母,当遇到大写字母时转化为小写,一旦不相等返回false,直至快慢指针相遇,跳出循环

代码实现

class Solution {
public:
    bool isPalindrome(string s) {
        int j=s.size()-1;
        int i=0;
        while(i<j)
        {
           while (!isalnum(s[i])&&i<j)
            {
               i++;
            }
                if(s[i]>='A'&&s[i]<='Z')
                {
                    s[i]=s[i]+32;
                }
                while(!isalnum(s[j])&&i<j)
                {
                    j--;
                }
                    if(s[j]>='A'&&s[j]<='Z')
                    {
                        s[j]=s[j]+32;
                    }
                    if(s[i]==s[j])
                    {
                        i++;
                        j--;
                    }
                    else{return false;}
        }
        return true;
    }
};

力扣73矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

示例 1:

输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
示例 2:

输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

提示:

m == matrix.length
n == matrix[0].length
1 <= m, n <= 200
-231 <= matrix[i][j] <= 231 - 1

题目分析

给定一个矩阵,当矩阵出现0时,0所在的行与列都置0

解题思路

在双重循环中利用两个数组标记矩阵中0所在的行与列
再利用双重循环,如果有标记,那么那一行与列都置零

代码实现

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        vector<int>row(m),col(n);
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(matrix[i][j]==0){
                row[i]=col[j]=true;
                }
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(row[i]||col[j]){
                    matrix[i][j]=0;
                }
            }
        }
    }
};

力扣21合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:

输入:l1 = [], l2 = []
输出:[]
示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列

题目分析

将两个有序链表合并为一个有序链表

解题思路

另外定义新链表,依次比较两个链表的值再存入
或直接使用递归将其拼接
问题:使用递归将返回l1还是l2呢?
随着递归使用,当有一个链表为空时,返回另外一个
注意:最后的判断条件不可为l1->val>=l2->next,因为必须要进入if else 语句,否则没有返回值,编译报错
如果新建链表则没有此问题

代码实现

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(l1==NULL)
        {
            return l2;
        }else if(l2==NULL)
        {
            return l1;
        }else if(l1->val<l2->val)
        {
            l1->next=mergeTwoLists(l1->next,l2);
            return l1;
        }else //不能写l1->next>=l2->next
        {
            l2->next=mergeTwoLists(l1,l2->next);
            return l2;
        }
    }
};


力扣147对链表进行插入排序

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

插入排序 算法的步骤:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。

对链表进行插入排序。

示例 1:

输入: head = [4,2,1,3]
输出: [1,2,3,4]
示例 2:

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

提示:

列表中的节点数在 [1, 5000]范围内
-5000 <= Node.val <= 5000

题目分析

对链表进行插入排序
插入排序:从数组(链表)的第一个数开始,每次遍历数组寻找合适位置,直至数组的最后一个数排序完

解题思路

因为有可能在头结点之前插入结点,所以我们要设计一个虚拟头结点便于操作
首先设计三个指针
p记录要改变的结点位置
q记录改变结点的下一个位置,防止丢失结点
pre记录虚拟头结点,实现每一次遍历链表
然后
1.当p的值小于等于q的值就不需要移动结点,同时将p,q指向的结点位置向后移一位
2.当p的值大于q时,pre指针遍历链表,寻找第一个大于p值的结点,并将pre放在此节点的前一个位置,便于插入

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        if (head == nullptr) {
            return head;
        }
        ListNode*dummy=new ListNode(0);
        dummy->next=head;
        ListNode*cur=dummy;
        ListNode*p=head;
        ListNode*q=head->next;
        while(q!=NULL){
            if(p->val<=q->val){
                p=p->next;
            }else {
                ListNode*pre=dummy;
                while(pre->next->val<=q->val){
                    pre=pre->next;
                }
                p->next=q->next;
                q->next=pre->next;
                pre->next=q;
            }
            q=p->next;
        }
        return dummy->next;
    }
};

力扣309买卖股票的最佳时期含冷冻时期

给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: prices = [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
示例 2:

输入: prices = [1]
输出: 0

提示:

1 <= prices.length <= 5000
0 <= prices[i] <= 1000

题目分析

求得卖出股票的最大利益,由于冷冻期的存在,不能连续两天对股票进行操作,并且手里最多只能持有一只股票

解题思路

利用动态规划和贪心的思想
f[i][0]: 手上持有股票的最大收益
f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益
对f[i][0]分析:1.第i天无操作,最大收益为第i-1天 2.第i天买入股票那么第i-1天不持有股票且不能进入冷冻期
f[i][0]=max(f[i-1][0],f[i-1][2]-prices[i])
对f[i][1]分析:处于冷冻期所以第i天卖出了股票
f[i][1]=f[i-1][0]+prices[i]
对f[i][2]分析:第i天不在冷冻期所以第i-1天没操作,又不持有股票,所以第i-1天也没有股票,那么取第i-1天在不在冷冻期的最大值
f[i][2]=max(f[i−1][1],f[i−1][2])

代码实现

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.empty()) {
            return 0;
        }

        int n = prices.size();
        // f[i][0]: 手上持有股票的最大收益
        // f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
        // f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益
        vector<vector<int>> f(n, vector<int>(3));
        f[0][0] = -prices[0];
        for (int i = 1; i < n; ++i) {
            f[i][0] = max(f[i - 1][0], f[i - 1][2] - prices[i]);
            f[i][1] = f[i - 1][0] + prices[i];
            f[i][2] = max(f[i - 1][1], f[i - 1][2]);
        }
        return max(f[n - 1][1], f[n - 1][2]);
    }
};

力扣187重复的DNA序列

DNA序列 由一系列核苷酸组成,缩写为 ‘A’, ‘C’, ‘G’ 和 ‘T’.。

例如,“ACGAATTCCG” 是一个 DNA序列 。
在研究 DNA 时,识别 DNA 中的重复序列非常有用。

给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。

示例 1:

输入:s = “AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT”
输出:[“AAAAACCCCC”,“CCCCCAAAAA”]
示例 2:

输入:s = “AAAAAAAAAAAAA”
输出:[“AAAAAAAAAA”]

提示:

0 <= s.length <= 105
s[i]==‘A’、‘C’、‘G’ or ‘T’

题目分析

给你一串字符串,返回出现不止一次的长度为10的子串

解题思路

利用滑动窗口和哈希表,每次移动一个长度截取长度为10的子串,再用哈希表判断子串中的各个字母是否与之前重复,只当次数等于2时输出子串,防止输出重复子串

代码实现

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> p,tmp;
        int n=s.length();
        unordered_map<string,int>cnt;
        for(int j=0;j<=n-10;j++){
            string sub=s.substr(j,10);
            if(++cnt[sub]==2){
                tmp.push_back(sub);
            }
        }
        return tmp;
    }
};

力扣2517礼盒最大甜蜜度

给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k 。

商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。

返回礼盒的 最大 甜蜜度。

示例 1:

输入:price = [13,5,1,8,21,2], k = 3
输出:8
解释:选出价格分别为 [13,5,21] 的三类糖果。
礼盒的甜蜜度为 min(|13 - 5|, |13 - 21|, |5 - 21|) = min(8, 8, 16) = 8 。
可以证明能够取得的最大甜蜜度就是 8 。
示例 2:

输入:price = [1,3,1], k = 2
输出:2
解释:选出价格分别为 [1,3] 的两类糖果。
礼盒的甜蜜度为 min(|1 - 3|) = min(2) = 2 。
可以证明能够取得的最大甜蜜度就是 2 。
示例 3:

输入:price = [7,7,7,7], k = 2
输出:0
解释:从现有的糖果中任选两类糖果,甜蜜度都会是 0 。

提示:

2 <= k <= price.length <= 105
1 <= price[i] <= 109

题目分析

选出k种糖果,使得这k种里任意两种糖果价格绝对差的最小值最大

解题思路

利用贪心和二分查找的思想
1,首先假设一个甜蜜度 mid,然后尝试在排好序的 price中找出 k 种糖果,并且任意两种相邻的价格差绝对值都大于 mid。如果可以找到这样的 k 种糖果,则说明可能存在更大的甜蜜度,返回true,修改左边界;如果找不到这样的 k 种糖果,则说明最大的甜蜜度只可能更小,返回false,修改右边界。
2.然后在假设一个甜蜜度 mid后,在排好序的 price中找 k 种糖果时,需要用到贪心的算法。即从小到大遍历 price 的元素,如果当前糖果的价格比上一个选中的糖果的价格的差大于 mid,则选中当前糖果,否则继续考察下一个糖果。

代码实现

class Solution {
public:
    int maximumTastiness(vector<int>& price, int k) {
        int n=price.size();
        sort(price.begin(),price.end());
        int left = 0, right = price[n - 1] - price[0];
        while (left < right) {
            int mid = (left + right + 1) >> 1;
            if (check(price, k, mid)) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

    bool check(const vector<int> &price, int k, int tastiness) {
        int prev = INT_MIN >> 1;
        int cnt = 0;
        for (int p : price) {
            if (p - prev >= tastiness) {
                cnt++;
                prev = p;
            }
        }
        return cnt >= k;
    }
};

大一下考核题

力扣238除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请 不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例 1:

输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

提示:

2 <= nums.length <= 105
-30 <= nums[i] <= 30
保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内

题目分析

输出一个数组,数组的第i位是除第i个数字的其他元素之积,不能使用除法

解题思路

利用前缀积和后缀积的思想,数组的每一位都等于它的前缀积×后缀积
注意:这里的前缀和后缀与正常不同,不能包含第i位

代码实现

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        
        vector<int> a(nums.size(),0),b(nums.size(),0);
        vector<int> ans(nums.size(),1);
        a[0]=1;
        b[nums.size()-1]=1;
        for(int i=1,j=nums.size()-2;j>=0;i++,j--){
           a[i]=a[i-1]*nums[i-1];
           b[j]=b[j+1]*nums[j+1];
        }
        for(int i=0;i<nums.size();i++){
            ans[i]=a[i]*b[i];
        }
        return ans;
    }
};

力扣394字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例 1:

输入:s = “3[a]2[bc]”
输出:“aaabcbc”
示例 2:

输入:s = “3[a2[c]]”
输出:“accaccacc”
示例 3:

输入:s = “2[abc]3[cd]ef”
输出:“abcabccdcdcdef”
示例 4:

输入:s = “abc3[cd]xyz”
输出:“abccdcdcdxyz”

提示:

1 <= s.length <= 30
s 由小写英文字母、数字和方括号 ‘[]’ 组成
s 保证是一个 有效 的输入。
s 中所有整数的取值范围为 [1, 300]

题目分析

有关括号的匹配的字符串问题

解题思路

当我们遇到括号的匹配时,首先想到的就是用栈来解决
设置两个栈nums,strs,分别来存放字符串中的数字与字符串,定义一个字符串res用于输出1.遇到数字用num记录,遇到字符串用res记录
2.遇到左括号时,把数字和字符串分别压入栈,再重置num为0,res为空
3.遇到右括号时,开始解码,取num的栈顶作为字符串重复的次数,重复将res加入栈内后,若栈顶还是字母,就会直接加到res之后,因为它们是同一级的运算,若是左括号,res会被压入str,作为上一层的运算

代码实现

class Solution {
public:
    string decodeString(string s) {
        string res = "";
        stack <int> nums;
        stack <string> strs;
        int num = 0;
        int len = s.size();
        for(int i = 0; i < len; ++ i)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                num = num * 10 + s[i] - '0';
            }
            else if((s[i] >= 'a' && s[i] <= 'z') ||(s[i] >= 'A' && s[i] <= 'Z'))
            {
                res = res + s[i];
            }
            else if(s[i] == '[') //将‘[’前的数字压入nums栈内, 字母字符串压入strs栈内
            {
                nums.push(num);
                num = 0;
                strs.push(res); 
                res = "";
            }
            else //遇到‘]’时,操作与之相配的‘[’之间的字符,使用分配律
            {
                int times = nums.top();
                nums.pop();
                for(int j = 0; j < times; ++ j)
                    strs.top() += res;
                res = strs.top(); //之后若还是字母,就会直接加到res之后,因为它们是同一级的运算
                                  //若是左括号,res会被压入strs栈,作为上一层的运算
                strs.pop();
            }
        }
        return res;
    }
};

力扣23合并k个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:

输入:lists = []
输出:[]
示例 3:

输入:lists = [[]]
输出:[]

题目分析

与合并2个有序链表类似

解题思路

先合并前两个链表,再不断将新链表与下一个链表合并

代码实现

class Solution {
public:
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (int i = 0; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
};

力扣232用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:

你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

提示:

1 <= x <= 9
最多调用 100 次 push、pop、peek 和 empty
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

题目分析

用栈实现队列

解题思路

C语言
myQueueCreate
功能:创建一个新的队列,并初始化栈顶指针。
myQueuePush
功能:将一个元素推入队列。
myQueuePop
功能:从队列中弹出一个元素。
如果 stkOut 是空的,它会从 stkIn 中取出所有元素并放入 stkOut 中,然后弹出 stkOut 的顶部元素。这是为了确保弹出的元素是队列中最先进入的元素。
myQueuePeek
功能:查看队列的顶部元素但不弹出。
myQueueEmpty
功能:检查队列是否为空。
myQueueFree
功能:释放队列。

代码分析

typedef struct {
    int stkInTop,stkOutTop;
    int stkIn[100],stkOut[100];
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));
    queue->stkInTop = 0;
    queue->stkOutTop = 0;
    return queue;
}

void myQueuePush(MyQueue* obj, int x) {
    obj->stkIn[(obj->stkInTop)++] = x;
}

int myQueuePop(MyQueue* obj) {
    int inTop = obj->stkInTop;
    int outTop = obj->stkOutTop;
    if(outTop == 0){
        while(inTop){
            obj->stkOut[outTop++] = obj->stkIn[--inTop];
        }
    }
    int res = obj->stkOut[--outTop];
    while(outTop){
        obj->stkIn[inTop++] = obj->stkOut[--outTop];
    }
    obj->stkInTop = inTop;
    obj->stkOutTop = outTop;
    return res;
}

int myQueuePeek(MyQueue* obj) {
    return obj->stkIn[0];
}

bool myQueueEmpty(MyQueue* obj) {
    return obj->stkInTop == 0 && obj->stkOutTop == 0;
}

void myQueueFree(MyQueue* obj) {
    obj->stkInTop = 0;
    obj->stkOutTop = 0;
}

力扣61旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
示例 2:

输入:head = [0,1,2], k = 4
输出:[2,0,1]

提示:

链表中节点的数目在范围 [0, 500] 内
-100 <= Node.val <= 100
0 <= k <= 2 * 109

题目分析

将旋转后的链表重新排序

解题思路

将链表存到数组中,再用三个reverse反转数组,再存入数组中
三个反转:先全部反转,再反转前k个,最后反转后k个

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(!head){
            return head;
        }
        ListNode*p=head;
        vector<int>arr;
        int n = 1;
        ListNode* iter = head;
        while (iter->next != nullptr) {
            iter = iter->next;
            n++;
        }
        int add = k % n;
        if (add == n) {
            return head;
        }
        while(p->next!=nullptr){
            arr.push_back(p->val);
             p=p->next;
        }
        arr.push_back(p->val);
        p=head;
        reverse(arr.begin(),arr.end());
        reverse(arr.begin(),arr.begin()+add);
        reverse(arr.begin()+add,arr.end());
        for(int i=0;i<arr.size();i++){
            p->val=arr[i];
            p=p->next;
        }
        return head;
    }
};

力扣392判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

进阶:

如果有大量输入的 S,称作 S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

致谢:

特别感谢 @pbrother 添加此问题并且创建所有测试用例。

示例 1:

输入:s = “abc”, t = “ahbgdc”
输出:true
示例 2:

输入:s = “axc”, t = “ahbgdc”
输出:false

提示:

0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成。

题目分析

判断s是否是t的子序列,其中可以有别的字符,但不能改变相对位置

解题思路

利用快慢指针,慢指针位于s,快指针位于t,只有快慢指针指向的字符相等时慢指针移动,快指针持续移动,当慢指针遍历完时(也就是快指针已经将慢指针指向的字符都匹配上)返回true

代码实现

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int slowindex,fastindex;
        if(s.size()==0)return true;
        for(fastindex=0,slowindex=0;fastindex<t.size();fastindex++)
        {
            if(s[slowindex]==t[fastindex])
            {
                if(++slowindex==s.size())
                return true;
            }
        }
        return false;
    }
};
  • 39
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值