codetop字符串刷题,刷穿地心!!不再畏惧!!暴打面试官!!

news2024/9/19 23:11:47

主要供自己回顾与复习,题源codetop标签字符串+近半年,会不断更新

  • 1.有效的括号字符串
  • 2.括号生成
  • 3.最长单词
  • 4.字符串转换整数(atoi)
  • 5.整数转罗马数字
  • 6.罗马数字转整数
  • 7.比较版本号
  • 8.最长公共前缀
  • 9.面试题17.15.最长单词
  • 10.验证IP地址
  • 11.面试题01.06.字符串压缩

1.有效的括号字符串

给你一个只包含三种字符的字符串,支持的字符类型分别是 ‘(’、‘)’ 和 ‘*’。请你检验这个字符串是否为有效字符串,如果是 有效 字符串返回 true 。

‘*’ 可以被视为单个右括号 ‘)’ ,或单个左括号 ‘(’ ,或一个空字符串 “”。

与用栈判断有效括号字符串的区别在于,这里的*很灵活,可以被当做左括号也可以被当做右括号,甚至可以被当做空,所以(*))也是true的,因为*被当做左括号了。

这题的解法也比较特别,不需要栈,只需要遍历一遍,记录左括号最大和最小的可能性:
如果遇到的是(,那么左括号无论最大还是最小都要+1
如果遇到的是),那么左括号最小的情况,是要-1,抵消一个,最大的情况,也要-1,因为不管怎么样,)始终是要抵消掉一个左括号的,即便是*当作左括号的情况
如果遇到的是*,那么左括号最小就是*抵消掉他一个左括号,减一个,左括号最大,就是*没有抵消他,而是算在他这边,+1个。

最后,lo表示到当前字符为止最小可能的左括号数,如果最终 lo <= 0,表示所有的左括号都有匹配的右括号,或者多余的 ‘*’ 被当作空字符处理,因此返回 true。

class Solution {
public:
    bool checkValidString(string s) {
        int lo = 0, hi = 0;//表示最低可能的左括号数和最高可能的左括号数
        for(auto c : s){
            if(c == '('){
                lo++;
                hi++;
            }
            else if(c == ')'){
                lo = max(0, lo - 1);
                hi--;
                if(hi < 0) return false;
            }
            else{
                hi++;
                lo = max(0, lo - 1);//遇到*的时候,左括号最小的情况是有一个左括号被*抵消掉了
            }
        }
        return lo <= 0;

    }
};

2.括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
eg:
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]

题目转换一下就是:现在有2n个位置,每个位置可以放置字符(或者),组成的所有括号组合中,由多少是合法的,这样听起来就很像回溯了,暴力穷举就可以了,合法的穷举需要满足以下两点:

  • 对于一个合法的括号组合的左括号数量一定等于右括号数量
  • 对于一个合法的括号字符串组合p,必然对于任何 0 <= i < size§ 都有:子串 p[0…i] 中左括号的数量都大于或等于右括号的数量。

因为从左往右计算的话肯定是左括号数量多,右括号逐步加多,最后相等,才能得到合法的括号组合嘛
用left记录还剩多少左括号,right记录还剩多少右括号

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        if(n == 0) return {};
        vector<string> res;
        string path;
        backtrack(n, n, path, res);
        return res;
    }
    void backtrack(int left, int right, string& path, vector<string>& res){
        if(left > right) return;//不合法
        if(left < 0 || right < 0) return;//不合法
        if(left == 0 && right == 0){
            res.push_back(path);
            return;
        }
        path.push_back('(');
        backtrack(left - 1, right, path, res);
        path.pop_back();

        path.push_back(')');
        backtrack(left, right - 1, path, res);
        path.pop_back();
    }
};

3.最长单词

给定一个单词列表 words,要求找到其中的 最长单词,该单词可以由其他单词(也在 words 中)组合而成。如果有多个符合条件的单词,返回字典序最小的那个。如果没有符合要求的单词,返回空字符串。

和动态规划刷题那篇blog传送中的单词拆分很像,可以一起学。

主函数longestWord作用是匹配之后如果当前单词符合组合条件,我们需要和当前结果比较其长度;如果长度相同,还要判断字典序。
辅助函数isMatch作用是匹配
使用dp,dp[i]表示0~i-1是否可以被拆分为字典中其他单词的组合。
遍历word的每个位置 i:i 表示我们当前处理的子串的结尾位置,即我们正在考虑从 word 的第一个字如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

要注意2点:

  • 第1点,单词拆分那一题没有newWord != word这个判断,因为两个题目的目的不一样,这个题目的word是从wordSet中拆出来的,单词拆分是给的另外一个词。
  • 第2点,j如果从1开始,那么substr就是(j - 1, i - (j - 1)),j如果从0开始,那么substr就是(j , i - j),总而言之j必须从1开始,这是为的dp的完整性
class Solution {
public:
    string longestWord(vector<string>& words) {
        string res = "";
        unordered_set<string> wordSet(words.begin(), words.end());
        for(const string& word : wordSet){
            if(isMatch(wordSet, word)){
                if(word.size() > res.size()) res = word;
                else if(word.size() == res.size() && word < res) res = word;
            }
        }
        return res;

    }
    bool isMatch(unordered_set<string>& wordSet, const string word){
        vector<bool> dp(word.size() + 1, false);
        dp[0] = true;
        for(int i = 1; i <= word.size(); i ++){
            for(int j = 0; j < i; j ++){
                string newWord = word.substr(j, i - j);
                if(newWord != word && wordSet.count(newWord) && dp[j]){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[word.size()];
    }
};

4.字符串转换整数(atoi)

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数。

函数 myAtoi(string s) 的算法如下:

  1. 空格:读入字符串并丢弃无用的前导空格(" ")
  2. 符号:检查下一个字符(假设还未到字符末尾)为 ‘-’ 还是 ‘+’。如果两者都不存在,则假定结果为正。
  3. 转换:通过跳过前置零来读取该整数,直到遇到非数字字符或到达字符串的结尾。如果没有读取数字,则结果为0。
  4. 舍入:如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被舍入为 −231 ,大于 231 − 1 的整数应该被舍入为 231 − 1 。
    返回整数作为最终结果。
class Solution {
public:
    int myAtoi(string s) {
        int res = 0;
        int index = 0, sign = 1;
        //丢弃前导空格
        while(index < s.size() && s[index] == ' ') index++;
        //检查符号
        if(index < s.size()){
            if(s[index] == '-'){
                sign = -1;
                index ++;
            }
            else if(s[index] == '+') index++;
        }
        //转换数字
        while(index < s.size() && isdigit(s[index])){
            int digit = s[index] - '0';

            //舍入计算
            if(res > (INT_MAX - digit) / 10){
                return (sign == 1) ? INT_MAX : INT_MIN;
            }
            //res * 10 + digit > int_max -> res > (int_max - digit) / 10
            res = res * 10 + digit;
            index++;
        }
        return res * sign;
    }
};

5.整数转罗马数字

七个不同的符号代表罗马数字:
符号 值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
  • 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式。

给定一个整数,将其转换为罗马数字。

900,400,90,40单领出来是有必要的,因为900不是DCCCC,而是CM

class Solution {
public:
    string intToRoman(int num) {
        vector<pair<int, string>> valueSymbol = {
            {1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},
            {100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"},
            {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"},
            {1, "I"}
        };
        string res = "";
        for(auto [value, symbol] : valueSymbol){
            while(num >= value){
                res += symbol;
                num -= value;
            }
        }
        return res;

    }
};

6.罗马数字转整数

在这里插入图片描述
4和9的特例用算法逻辑解决了,以IX为例,遍历到I的时候,发现 I 为 1,小于后续的 X 值为 10,所以执行减法,接下来遍历至X没有发现后续字符,或者X大于等于任何可能的后序字符,所以加上 X 的值。

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> symbolTovalue{
            {'M', 1000}, {'D', 500}, {'C', 100}, 
            {'L', 50}, {'X', 10}, {'V', 5},
            {'I', 1}
        };
        int res = 0;
        for(int i = 0; i < s.size(); i ++){
            int value = symbolTovalue[s[i]];
            if(i + 1 < s.size() && value < symbolTovalue[s[i + 1]]){
                res -= value;
            }else{
                res += value;
            }
        }
        return res;
    }
};

7.比较版本号

给你两个 版本号字符串 version1 和 version2 ,请你比较它们。版本号由被点 ‘.’ 分开的修订号组成。修订号的值 是它 转换为整数 并忽略前导零。

比较版本号时,请按 从左到右的顺序 依次比较它们的修订号。如果其中一个版本字符串的修订号较少,则将缺失的修订号视为 0。
返回规则如下:

  • 如果 version1 < version2 返回 -1,
  • 如果 version1 > version2 返回 1,
  • 除此之外返回 0。

eg1:
输入:version1 = “1.01”, version2 = “1.001”
输出:0
解释:忽略前导零,“01” 和 “001” 都代表相同的整数 “1”。
eg2:
输入:version1 = “1.0”, version2 = “1.0.0.0”
输出:0
解释:version1 有更少的修订号,每个缺失的修订号按 “0” 处理。

双指针做法,将两个字符串转换成整数

class Solution {
public:
    int compareVersion(std::string version1, std::string version2) {
        int i = 0, j = 0;
        int len1 = version1.size(), len2 = version2.size();

        while (i < len1 || j < len2) {
            // 获取 version1 中的下一个修订号
            int num1 = 0;
            while (i < len1 && version1[i] != '.') {
                num1 = num1 * 10 + (version1[i] - '0');
                i++;
            }
            i++; 

            // 获取 version2 中的下一个修订号
            int num2 = 0;
            while (j < len2 && version2[j] != '.') {
                num2 = num2 * 10 + (version2[j] - '0');
                j++;
            }
            j++; // Skip the dot in version2

            // 比较两个修订号
            if (num1 > num2) return 1;
            if (num1 < num2) return -1;
        }

        return 0;
    }
};

8.最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。

输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”

把字符串列表看成一个二维数组,然后用一个嵌套 for 循环计算这个二维数组前面有多少列的元素完全相同即可。

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int minLen = strs[0].size();
        for(string str : strs){
            if(str.size() < minLen) minLen = str.size();
        }
        int n = strs.size();//行
        string res = "";
        for(int i = 0; i < minLen; i ++){
            char curStr = strs[0][i];
            for(int j = 1; j < n; j ++){
                if(strs[j][i] != curStr) return res;
            }
            res += curStr;
        }
        return res;

    }
};

9.面试题17.15.最长单词

给定一组单词words,编写一个程序,**找出其中的最长单词,且该单词由这组单词中的其他单词组合而成。**若有多个长度相同的结果,返回其中字典序最小的一项,若没有符合要求的单词则返回空字符串。

输入: [“cat”,“banana”,“dog”,“nana”,“walk”,“walker”,“dogwalker”]
输出: “dogwalker”
解释: "dogwalker"可由"dog"和"walker"组成。

class Solution {
public:
    string longestWord(vector<string>& words) {
        if (words.empty() || words.size() <= 1) {
            return "";
        }

        unordered_set<string> wordSet(words.begin(), words.end());
        string res = "";

        for (const string& word : wordSet) {
            if (isMatch(wordSet, word)) {
                if (word.length() > res.length()) {
                    res = word;
                } else if (word.length() == res.length() && word < res) {
                    res = word;
                }
            }
        }

        return res;
    }

private:
    bool isMatch(const unordered_set<string>& wordSet, const string& word) {
        vector<bool> dp(word.length() + 1, false);
        dp[0] = true;

        for (int i = 1; i <= word.length(); ++i) {
            for (int j = 1; j <= i; ++j) {
                string cur = word.substr(j - 1, i - (j - 1));
                if (cur != word && wordSet.count(cur) && dp[j - 1]) {
                    dp[i] = true;
                    break;  // 找到一个有效的组合即可退出当前循环
                }
            }
        }

        return dp[word.length()];
    }
};

10.验证IP地址


正则表达式

#include <regex>
#include <string>

using namespace std;

class Solution {
public:
    bool ipv4(const string& ip) {
        regex pattern("(^((25[0-5]|2[0-4][0-9]|1\\d\\d|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1\\d\\d|[1-9][0-9]|[0-9])$)");
        return regex_match(ip, pattern);
    }
    
    bool ipv6(const string& ip) {
        regex pattern("(^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$)");
        return regex_match(ip, pattern);
    }
    
    string validIPAddress(const string& queryIP) {
        if (ipv4(queryIP)) return "IPv4";
        else if (ipv6(queryIP)) return "IPv6";
        else return "Neither";
    }
};

11.面试题01.06.字符串压缩

利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。

  • 遍历字符串,使用计数器记录每个连续字符的出现次数。
  • 当遇到不同字符时,将之前的字符以及计数拼接到结果字符串中。
  • 如果遍历到最后一个字符,将最后的字符及其计数添加到结果。
  • 最后,比较压缩后的字符串长度和原始字符串长度,返回长度短的那个。
class Solution {
public:
    string compressString(string s) {
        if(s.empty()) return s;  // 空字符串的处理
        int count = 1;
        string res = "";
        for(int i = 1; i < s.size(); i ++){
            if(s[i] == s[i - 1]){
            	// 当前字符和前一个字符相同,计数加1
                count ++;
            }
            else{
            	// 当前字符和前一个字符不同,将前一个字符及其计数添加到结果
                res += s[i - 1];// 添加字符
                res += to_string(count);// 添加计数
                count = 1;// 重置计数
            }
        }
        //处理最后一个字符串
        res += s[s.size() - 1];// 添加最后一个字符
        res += to_string(count);// 添加最后一个字符的计数
        // 如果压缩后的字符串长度不小于原字符串长度,返回原字符串
        return res.size() < s.size() ? res : s;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2147241.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

介绍一下常用的激活函数?

常用的激活函数 Sigmoid函数Tanh函数ReLU函数Leaky ReLU函数Softmax函数 Sigmoid函数 特点&#xff1a; 将任意实数映射到(0,1)区间内&#xff0c;输出值可以作为概率来解释。 函数平滑且易于求导&#xff0c;但其导数在两端趋近于0&#xff0c;即存在梯度消失问题。 输出值不…

CWFED:自然灾害检测数据集(猫脸码客 第192期)

Cyclone Wildfire Flood Earthquake Database 在自然灾害频发的今天&#xff0c;准确、及时地获取并分析相关数据对于灾害预防、预警及响应至关重要。为此&#xff0c;Cyclone Wildfire Flood Earthquake Database&#xff08;以下简称CWFE Database&#xff09;应运而生&…

计算机毕业设计 农场投入品运营管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

gcc升级(含命令行升级、手动升级两种方式)

gcc升级 1.yum源替换1.1 备份原始repo配置文件1.2 重新配置CentOS-Base.reporepo文件1.3 清除缓存并重新创建 2. gcc安装3.命令行升级gcc4.手动升级4.1 安装包下载4.2 解压4.3 gcc升级4.3.1 依赖拉取4.3.2 gmp安装4.3.3 mpfr安装4.3.4 mpc安装4.3.5 gcc编译、安装 4.4 gcc命令配…

Linux环境变量进程地址空间

目录 一、初步认识环境变量 1.1常见的环境变量 1.2环境变量的基本概念 二、命令行参数 2.1通过命令行参数获取环境变量 2.2本地变量和内建命令 2.3环境变量的获取 三、进程地址空间 3.1进程&#xff08;虚拟&#xff09;地址空间的引入 3.2进程地址空间的布局和理解 …

简易CPU设计入门:本CPU项目的指令格式

在这一节里面&#xff0c;主要是理论知识&#xff0c;基本上不讲代码。不过&#xff0c;本项目的代码包&#xff0c;大家还是需要下载的。 本项目的代码包的下载方法&#xff0c;参考下面的链接所指示的文章。 下载本项目代码 本节&#xff0c;其实是要讲本项目CPU的指令集。…

大模型蒸馏技术

一篇题为《The Mamba in the Llama: Distilling and Accelerating Hybrid Models》的论文证明&#xff1a;通过重用注意力层的权重&#xff0c;大型 transformer 可以被蒸馏成大型混合线性 RNN&#xff0c;只需最少的额外计算&#xff0c;同时可保留其大部分生成质量。 先来说…

Python学习——【2.1】if语句相关语法

文章目录 【2.1】if语句相关一、布尔类型和比较运算符&#xff08;一&#xff09;布尔类型&#xff08;二&#xff09;比较运算符 二、if语句的基本格式※、练习 三、if-else组合判断语句※、练习 四、if-elif-else多条件判断语句※、练习 五、判断语句的嵌套※、实战案例 【2.…

AlexNet项目图片分类通用模型代码

目录 一&#xff1a;建立AlexNet模型&#xff08;在model文件中写&#xff09; 1.构造5层卷积层 2.构造3层神经网络层 3.forward函数 4.模型最终代码 二&#xff1a;训练数据&#xff08;在train中写&#xff09; 1.读出数据 2.训练 3. 测试模型更新参数 4.完整的训练…

Datawhile 组队学习Tiny-universe Task01

Task01&#xff1a;LLama3模型讲解 仓库链接&#xff1a;GitHub - datawhalechina/tiny-universe: 《大模型白盒子构建指南》&#xff1a;一个全手搓的Tiny-Universe 参考博客&#xff1a;LLaMA的解读与其微调(含LLaMA 2)&#xff1a;Alpaca-LoRA/Vicuna/BELLE/中文LLaMA/姜子…

新的突破,如何让AI与人类对话变得“顺滑”:Moshi背后的黑科技

你有没有想过,当我们跟智能音箱、客服机器人或者语音助手对话时,它们是怎么“听懂”我们说的话,又是怎么迅速给出回应的?就好像你对着Siri、Alexa说一句:“给我订个披萨”,它立刻明白你想要干嘛,然后帮你下单。背后的技术其实比我们想象的要复杂得多,但现在,有了Moshi…

Qt_布局管理器

目录 1、QVBoxLayout垂直布局 1.1 QVBoxLayout的使用 1.2 多个布局管理器 2、QHBoxLayout水平布局 2.1 QHBoxLayout的使用 2.2 嵌套的Layout 3、QGridLayout网格布局 3.1 QGridLayout的使用 3.2 设置控件大小比例 4、QFormLayout 4.1 QFormLayout的使用 5、…

【2024】前端学习笔记8-内外边距-边框-背景

学习笔记 外边距&#xff1a;Margin内边距&#xff1a;Padding边框&#xff1a;Border背景&#xff1a;Background 外边距&#xff1a;Margin 用于控制元素周围的空间&#xff0c;它在元素边框之外创建空白区域&#xff0c;可用于调整元素与相邻元素&#xff08;包括父元素和兄…

AI预测福彩3D采取888=3策略+和值012路或胆码测试9月19日新模型预测第92弹

经过90多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;90多期一共只错了10次&#xff0c;这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了&#xff0…

教育政策与智能技术:构建新时代教师队伍

据最新统计&#xff0c;我国目前拥有各级各类教师共计1891.8万人&#xff0c;这一庞大的教师群体不仅支撑起了全球规模最大的教育体系&#xff0c;更成为了推动教育创新与变革的主力军。面对教育数字化的不断发展&#xff0c;育人内容、目标要求、方式方法的全面升级&#xff0…

【测向定位】差频MUSIC算法DOA估计【附MATLAB代码】

​微信公众号&#xff1a;EW Frontier QQ交流群&#xff1a;554073254 摘要 利用多频处理方法&#xff0c;在不产生空间混叠的情况下&#xff0c;估计出高频区域平面波的波达方向。该方法利用了差频&#xff08;DF&#xff09;&#xff0c;即两个高频之间的差。这使得能够在可…

鹏鼎控股社招校招入职SHL综合能力测评:高分攻略及真题题库解析答疑

鹏鼎控股&#xff08;深圳&#xff09;股份有限公司&#xff0c;成立于1999年4月29日&#xff0c;是一家专注于印制电路板&#xff08;PCB&#xff09;的设计、研发、制造与销售的高新技术企业。公司总部位于中国广东省深圳市&#xff0c;并在全球多个地区设有生产基地和服务中…

【软考】数据字典(DD)

目录 1. 说明2. 数据字典的内容2.1 说明2.2 数据流条目2.3 数据存储条目2.4 数据项条目2.5 基本加工条目 3. 数据词典管理4. 加工逻辑的描述4.1 说明4.2 结构化语言4.3 判定表4.3 判定树 5. 例题5.1 例题1 1. 说明 1.数据流图描述了系统的分解&#xff0c;但没有对图中各成分进…

软件自动定时启动器-添加可执行文件软件,设置启动的时间,也可以设置关闭的时间-供大家学习研究参考

点击添加软件&#xff0c;可以添加可执行文件软件&#xff0c;设置启动的时间&#xff0c;也可以设置关闭的时间 注意&#xff0c;时间为00&#xff1a;00&#xff1a;00 等于没设置&#xff0c;这个时间不在设置范围&#xff0c;其他任何时间都可以。 下载地址&#xff1a; h…

【C++ Primer Plus习题】16.9

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <ctime> #include <v…