剑指offer 刷题7

目录

圆圈中最后剩下的数(约瑟夫问题) 3/16

 求1+2+3+...+n 

不用加减乘除做加法

把字符串转换成整数

正则表达式匹配

表示数值的字符串

数据流中的中位数

滑动窗口的最大值

矩阵中的路径

机器人的运动范围

剪绳子

字符流中第一个不重复的字符


圆圈中最后剩下的数(约瑟夫问题) 3/16

参考:https://www.nowcoder.com/questionTerminal/11b018d042444d4d9ca4914c7b84a968

参考:https://blog.csdn.net/qq_41822235/article/details/82382422

隐函数f(n,m)为在n个数字中每次删除第m个数字最后剩下的数字。观察图1的右边一列,套用定义,最后剩下的数字是f(n-1,m)。还需要用它的值反解出真实的数字(逆映射)。

Y->X: x = (y+k+1)%n 

思路:【找规律】

n个人编号0 ~ n -1;

第一个删除的人的编号:(m - 1)%n = k;

第一次删除之后剩下的人的编号:k+1, k+2,……n-1, 0, 1,……k-1;(共n-1个元素),设为f(n,m)

第二次将要删除的编号0 ~ n -2:   0,   1,……………………n-2;(共n-1个元素)设为y

f(n,m):意思是从n个数每次删除第m个数字之和剩下的数字。y为将要从n-1个数字中删除第m个数,设y =f(n-1,m)+b。b为一个未知的多项式。

f(n,m) = (y+k+1)%n = (f(n-1,m)+m)%n 

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n == 0 || m == 0)
            return -1;
        if(n == 1)
            return 0;
        return (LastRemaining_Solution(n-1,m) + m) % n;//【递归】
    }
};

 求1+2+3+...+n 

参考:https://www.nowcoder.com/questionTerminal/7a0da8fc483247ff8800059e12d7caf1?f=discussion

思路:要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

使用【递归】,递归终止条件为n == 0

如何实现n==0时候停止:逻辑与&&,当条件n >0为假的时候,停止

sum = 

链接:https://www.nowcoder.com/questionTerminal/7a0da8fc483247ff8800059e12d7caf1?f=discussion
来源:牛客网

解题思路:
1.需利用逻辑与的短路特性实现递归终止。 2.当n==0时,(n>0)&&((sum+=Sum_Solution(n-1))>0)只执行前面的判断,为false,然后直接返回0;
3.当n>0时,执行sum+=Sum_Solution(n-1),实现递归计算Sum_Solution(n)。
    public int Sum_Solution(int n) {
        int sum = n;
        boolean ans = (n>0)&&((sum+=Sum_Solution(n-1))>0);
        return sum;
    }
或者:

class Solution {
public:
    int Sum_Solution(int n) {
        int ans = n;
        ans && (ans += Sum_Solution(n - 1));
        return ans;
    }
};

不用加减乘除做加法

参考:https://www.nowcoder.com/questionTerminal/59ac416b4b944300b617d4f7f111b215?f=discussion

思路:【位运算】

1 两数异或^结果:为0(11或者00),为1(01或者10),相当于按位相加,没考虑进位

2 两数相与&结果:为0(00或者01或者10),为1(11),相当于求进位,要左移一位

3 将1、2结果相加

退出循环条件是进位为0,用或|将两个数加起来,由于进位变成0,所以直接输出当进位为0时候,对应的相与结果,即为最终结果。

举例:

递归:
class Solution {
public:
    int Add(int num1, int num2)
    {
        if (num2 == 0) return num1;
        return Add(num1^num2, (num1&num2)<<1 );
    }
};
非递归,循环
class Solution {
public:
    int Add(int num1, int num2)
    {
        while (num2!=0) {//终止条件,进位为0000
            int temp = num1^num2;//temp保存按位相加的结果
            num2 = (num1&num2)<<1;//num2保存进位的结果
            num1 = temp;//num1保存按位相加的结果
        }
        return num1;//输出进位为0时候,按位相加的结果
    }
};

把字符串转换成整数

参考:https://www.cnblogs.com/hyhy904/p/11075531.html

边界条件:

数据上下 溢出

空字符串

只有正负号

有无正负号

错误标志输出

思路:【字符串转整数】【边界条件】

0 整体长度为0 ,return0

1 如果第一个字符是空格,忽略;找到第一个非空格字符,可以是数字或者+ -

      1.1如果+-之后没有数字,return 0

2 找之后的字符串中是否遇到非法字符,有非法字符,return 0

3 之后的字符串中没有非法字符,将其转换成整数A

4 比较A是否在INT_MAX(2^31 − 1)和INT_MIN(−2^31)之间,不在,输出0

class Solution {
public:
    int StrToInt(string str) {
        if(str.size() == 0)//字符串长度为0
            return 0;//出口A
        long long num = 0;
        bool tag = true;//标记正负符号
        if(str[0] == '-')
            tag = false;//如果负号,标记为false
        for(int i = (str[0] == '+' || str[0] == '-' ? 1 : 0); i < str.size(); ++i){
            //当第一个字符为正负号时候,从第二个字符开始 i=1。否则从第一个字符开始i=0
            if(str[i] >= '0' && str[i] <= '9'){//【易错】字符在0-9范围内
                num = num * 10 + (str[i] - '0');//转为整数,因为前面的num是大数,每向后扫描一位,num乘以10
            }
            else{
                num = 0;//出口B,遇到非法字符,返回0,直接跳出
                break;
            }
        }
        num = tag ? num : (-num);//根据正负号修正num
        if(num > INT_MAX || num < INT_MIN)//num超过了int的范围,返回0
            return 0;//出口C
        return (int)num;//出口D,满足以上所有条件,返回最终结果
    }
};

 

正则表达式匹配

参考:https://www.nowcoder.com/questionTerminal/45327ae22b7b413ea21df13ee7d6429c?f=discussion

链接:https://www.nowcoder.com/questionTerminal/45327ae22b7b413ea21df13ee7d6429c?f=discussion
来源:牛客网

参考:https://www.cnblogs.com/developing/articles/11042856.html

待补图
【字符串】【逻辑判断】

class Solution {
public:
    bool match(char* str, char* pattern)
    {
        if (*str == '\0' && *pattern == '\0')
            return true;//两个都为空
        if (*str != '\0' && *pattern == '\0')
            return false;//str不为空,pattern为空
        //if the next character in pattern is not '*'
        //如果pattern下一个字符不是*
        if (*(pattern+1) != '*')
        {
            if (*str == *pattern || (*str != '\0' && *pattern == '.'))//比较当前元素是否相同,或者 str到达末尾且pattern当前为.
                return match(str+1, pattern+1);//相同,二者同时后移一位
            else
                return false;//不同,返回false
        }
        //if the next character is '*'
        //如果pattern下一个字符是*
        else
        {
            if (*str == *pattern || (*str != '\0' && *pattern == '.'))//【易错:判断str到末尾的情况】当前元素可以匹配上,或者 str到达末尾且pattern当前为.
                //1 pattern的x*当作0,pattern后移两位
                //2 pattern的x*不仅匹配当前的str,还能当作多个,与str下一位比较,str后移一位,pattern不变
                //2中的匹配1个或多个看作一种情况:
                /*
                当‘*’匹配1个或多个时,str当前字符移向下一个,pattern当前字符
                不变。(这里匹配1个或多个可以看成一种情况,因为:当匹配一个时,由于str移到了下一个字符,
                而pattern字符不变,match(str+1, pattern);
                就再次回到pattern的x*被当做0的情况,进入了match(str, pattern+2);
                二者加起来相当于match(str+1, pattern+2);
                当匹配多于一个字符时,相当于从str的下一个字符继续开始匹配)
                */
                return match(str, pattern+2) || match(str+1, pattern);
            else
                return match(str, pattern+2);//3 当前字符不能匹配,x*当作0,pattern后移两位
        }
    }
};

 

表示数值的字符串

【正则表达式】https://www.cnblogs.com/silentteller/p/12096761.html

链接:https://www.nowcoder.com/questionTerminal/6f8c901d091949a5837e24bb82a731f2?f=discussion
来源:牛客网

/*

以下对正则进行解释:

[\\+\\-]?            -> 正或负符号出现与否

\\d*                 -> 整数部分是否出现,如-.34 或 +3.34均符合

(\\.\\d+)?           -> 如果出现小数点,那么小数点后面必须有数字;

                        否则一起不出现

([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现,

                        紧接着必须跟着整数;或者整个部分都不出现

*/

常规:

class Solution {
public:
    bool isNumeric(char* str) {
        // 标记符号、小数点、e是否出现过
        bool sign = false, decimal = false, hasE = false;
        for (int i = 0; i < strlen(str); i++) {
            if (str[i] == 'e' || str[i] == 'E') {//出现e,e后面一定要接数字
                if (i == strlen(str)-1) return false; // 如果e是末尾,不行
                if (hasE) return false;  // 不能同时存在两个e
                hasE = true;
            } else if (str[i] == '+' || str[i] == '-') {
                // 第二次出现+-符号,则必须紧接在e之后
                if (sign && str[i-1] != 'e' && str[i-1] != 'E') return false;
                // 第一次出现+-符号,且不是在字符串开头,则也必须紧接在e之后
                if (!sign && i > 0 && str[i-1] != 'e' && str[i-1] != 'E') return false;
                sign = true;
            } else if (str[i] == '.') {
              // e后面不能接小数点,小数点不能出现两次
                if (hasE || decimal) return false;
                decimal = true;
            } else if (str[i] < '0' || str[i] > '9') // 不合法字符
                return false;
        }
        return true;
    }
};

数据流中的中位数

参考:https://www.cnblogs.com/silentteller/p/12119109.html

【priority_queue】【最大堆】【最小堆】【中位数】

最大堆放较小的,保证堆顶最大

最小堆放较大的,保证堆顶最小

当两个堆元素个数相等,中位数 = 两个堆顶元素值/2.0

当最大堆多一个,中位数=最大堆的堆顶元素

怎么平衡元素,保证中位数一直在堆顶?

具体见代码的两个if

class Solution {
    
public:
    void Insert(int num){
 
     //每次插入小顶堆的是当前大顶堆中最大的数
    //每次插入大顶堆的是当前小顶堆中最小的数
    //这样保证小顶堆中的数永远大于等于大顶堆中的数
    //中位数就可以方便地从两者的根结点中获取了
        if(p.empty() || num <= p.top()) p.push(num);//元素小于最大堆堆顶,压入最大堆
        else q.push(num);//否则压入最小堆
        if(p.size() == q.size() + 2) q.push(p.top()), p.pop();//最大堆比最小堆多两个,把最大堆top给最小堆
        if(p.size() + 1 == q.size()) p.push(q.top()), q.pop();//最大堆比最大堆少一个,将最小堆top给最大堆
//之所以最大堆比最小堆多两个,是因为num<=最大堆的堆顶,意味着插入数字可能和堆顶相等,匀出来一个给最小堆
//之所以最小堆多一个,是因为压入最小堆的都是比插入之前元素小的值,所以每次插入之后最小堆顶多比最大堆多一个,输出的中位数是最大堆堆顶,所以保证当size为奇数时,多出来的那个数字放在最大堆堆顶
    }
    double GetMedian(){ 
      return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
    }
private:
    priority_queue<int, vector<int>, less<int> > p;//最大堆,存较小的数,堆顶最大
    priority_queue<int, vector<int>, greater<int> > q;//最小堆,存较大的数,堆顶最小
     
};

滑动窗口的最大值

参考:https://blog.csdn.net/weixin_39485901/article/details/91493277

参考:https://www.cnblogs.com/silentteller/p/12119585.html

用一个双端队列,队列第一个位置保存当前窗口的最大值,当窗口滑动一次

1.判断当前最大值是否过期

2.新增加的值从队尾开始比较,把所有比他小的值丢掉

借助一个辅助队列(双端队列),从头遍历数组,根据如下规则进行入队列或出队列操作: 
1. 如果队列为空,则当前数字入队列 
2. 如果当前数字大于队列尾,则删除队列尾,直到当前数字小于等于队列尾,或者队列空,然后当前数字入队列 
3. 如果当前数字小于队列尾,则当前数字入队列 
4. 如果队列头超出滑动窗口范围,则删除队列头 
这样能始终保证队列头为当前的最大值

原文链接:https://blog.csdn.net/qq_32805671/article/details/84590348

数组索引插入元素当前滑动窗口队列中的数据当前最大值操作说明
0222 当前队列为空,队尾压入2
132 33 3>2,队尾删除2,队尾压入3
242 3 4444 > 3, 队尾删除3,队尾压入4,将4保存进结果vector
323 4 24 242<4,队尾压入2,检查窗口范围
464 2 666 
522 6 26 26 
656 2 56  56 
712 5 1 5  15 

 

 

 

 

 

 

 

 

 

 

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> res;//保存结果
        deque<int> deq;//辅助双向队列
        for(int i = 0; i < num.size(); ++i){//扫描数组
            while(!deq.empty() && num[deq.back()] < num[i])//当队列非空 且 队尾值小于将要压入的元素
                deq.pop_back();//队列末尾元素弹出去,直到队列为空,或者要压入的元素小于队尾
            deq.push_back(i);//压入元素
            if(deq.front() == i-size)//如果队首超出了滑动窗口范围,弹出队首元素
                deq.pop_front();
            if(i >=  size-1)
                res.push_back(num[deq.front()]);//保存队首元素
        }
        return res;
    }
};

矩阵中的路径

【图】【深度优先搜索】【回溯】

 

/*基本思想:
0.根据给定数组,初始化一个标志位数组,初始化为false,表示未走过,true表示已经走过,不能走第二次
1.根据行数和列数,遍历数组,先找到一个与str字符串的第一个元素相匹配的矩阵元素,进入judge
2.根据i和j先确定一维数组的位置,因为给定的matrix是一个一维数组
3.确定递归终止条件:越界,当前找到的矩阵值不等于数组对应位置的值,已经走过的,这三类情况,都直接false,说明这条路不通
4.若k,就是待判定的字符串str的索引已经判断到了最后一位,此时说明是匹配成功的
5.下面就是本题的精髓,递归不断地寻找周围四个格子是否符合条件,只要有一个格子符合条件,就继续再找这个符合条件的格子的四周是否存在符合条件的格子,直到k到达末尾或者不满足递归条件就停止。
6.走到这一步,说明本次是不成功的,我们要还原一下标志位数组index处的标志位,进入下一轮的判断。*/
class Solution {
public:
	bool hasPath(char* matrix, int rows, int cols, char* str)
	{
		if (matrix == NULL || rows < 1 || cols < 1 || str == NULL)
			return false;//如果矩阵为空,或者行列<1,str为空,则找不到
            
		bool* visited = new bool[rows*cols];              //定义一个辅助矩阵,用来标记路径是否已经进入了每个格子
		memset(visited, 0, rows*cols);
		int pathLength = 0;
		for (int row = 0;row < rows;++row)                //该循环是为了实现从任何一个位置出发,寻找路径
		{
			for (int col = 0; col < cols;++col)
			{
				if (hasPathCore(matrix, rows, cols, row, col, str, pathLength, visited))
					return true;
			}
		}
		delete[] visited;
		return false;
	}
 
	/*此函数用来判断在当前路径满足条件下,相邻格子中是否存在一个格子满足条件*/
	bool hasPathCore(char* matrix, int rows, int cols, int row, int col, char* str, int& pathLength, bool* visited)
	{
		if (str[pathLength] == '\0')
			return true;//回溯出口A,路径全部找到了,遍历到了str的末尾结束符
		bool hasPath = false;
		if (row >= 0 && row < rows&&col >= 0 && col < cols&&matrix[row*cols + col] == str[pathLength] && !visited[row*cols + col])
		{
        //找到了符合的字符
			++pathLength;
			visited[row*cols + col] = true;
			/*如果矩阵格子(row,col)与路径字符串中下标为pathLength的字符一样时,
			从它的4个相邻格子中寻找与路径字符串下标为pathLength+1的字符相等的格子*/
			hasPath = hasPathCore(matrix, rows, cols, row, col - 1, str, pathLength, visited) || 
				hasPathCore(matrix, rows, cols, row - 1, col, str, pathLength, visited) || 
				hasPathCore(matrix, rows, cols, row, col + 1, str, pathLength, visited) || 
				hasPathCore(matrix, rows, cols, row + 1, col, str, pathLength, visited);
			if (!hasPath)                                  
			{
				--pathLength;           //如果没找到,则说明当前第pathLength个字符定位不正确,返回上一个位置重新定位
				visited[row*cols + col] = false;
			}
		}
		return hasPath;
	}
};

或,暂时还有点迷惑

class Solution {
public:
    bool hasPath(char* matrix, int rows, int cols, char* str)
    {
        for(int i = 0; i < rows; i++){//建立vector,将矩阵中元素都存入vector
            vector<char> temp;
            for(int j = 0; j < cols; ++j){
                temp.push_back(*(matrix + i * cols + j));
            }
            res.push_back(temp);
        }
        
        vector<vector<int>> flag(rows, vector<int>(cols, 0));//新建二维数组,rows*cols大小,初始化为0
        for(int i = 0; i < rows; ++i){
            for(int j = 0; j < cols; ++j){
                if(helper(str, i, j, flag)){//如果所有路径被找到了,匹配成功,返回true
                    return true;//出口A
                }
            }
        }
        return false;//出口B,矩阵遍历结束还是没找到,匹配失败
    }
    
    bool helper(char* str, int x, int y, vector<vector<int>> flag){//待匹配字符串,行,列,标志位
        if(*str == '\0')
            return true;//出口A,待匹配字符串被匹配完了,匹配工作结束
        if(x < 0 || x >= res.size() || y < 0 || y >= res[0].size() || res[x][y] != *str || flag[x][y] == 1)
            return false;//非法输入:x y 超过了行和列的范围;x.y对应的矩阵元素不等于待匹配字符;当前元素被访问过
        flag[x][y] = 1;//输入合法,进行了访问,则更改标志位符号
        //在当前元素的上下左右,寻找下一位匹配的字符
        bool hasFind = helper(str+1, x+1, y, flag)
            || helper(str+1, x-1, y, flag)
            || helper(str+1, x, y+1, flag)
            || helper(str+1, x, y-1, flag);
        flag[x][y] = 0;
        return hasFind;
    }
private:
    vector<vector<char>> res;
};

机器人的运动范围

参考:https://www.cnblogs.com/silentteller/p/12124725.html

/*链接:https://www.nowcoder.com/questionTerminal/6e5207314b5241fb83f2329e89fdecc8?f=discussion
来源:牛客网*/

//思路:dfs,搜索四个方向,vis记录该方格是否被搜索过,
// 预判方格是否合法,合法就从该方格接着搜索
const int MAXN=100;
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};    //四个方向 
int vis[MAXN][MAXN]={0};    //记录数组
int sum;    //记录结果
 
class Solution {
public:
    void dfs(int x,int y,int k,int m,int n)
    {
        vis[x][y]=1;
        for(int i=0;i<=3;++i)
        {
            int newx=x+dx[i],newy=y+dy[i];
            //预判方格是否合法,合法就从该方格接着搜索
       if(vis[newx][newy]==0&&newx>=0&&newx<m&&newy>=0&&newy<n&&(newx%10+newx/10+newy%10+newy/10<=k))
            {
                ++sum;
                dfs(newx,newy,k,m,n);
            }
        }
    }
    int movingCount(int k, int rows, int cols)
    {
        if(k<0)
            return 0;
        memset(vis,0,sizeof(vis));
        sum=1;
        dfs(0,0,k,rows,cols);
        return sum;
         
    }
};

或者

class Solution {
public:
    int movingCount(int threshold, int rows, int cols)
    {
        vector<vector<int>> visit(rows, vector<int>(cols, 0));//新建标志位数组,初始化为0,表示没被访问过
        int count = helper(threshold, 0, 0, visit);//记录能到达格子数
        return count;
    }
    
    int helper(int threshold, int x, int y, vector<vector<int>> &visit){
        int c = 0;//初始化能到达格子数为0
        if(x < 0 || x > visit.size()-1 || y < 0 || y > visit[0].size()-1 || (getSum(x)+getSum(y)) > threshold || visit[x][y] == 1){
            return 0;//出口 输入非法:行 列超出范围、当前行坐标和列坐标的数位之和大于limit、当前格子被访问过
        }
        visit[x][y] = 1;//当前格子被访问了
        //访问上下左右四个元素
        c = 1 + helper(threshold, x+1, y, visit) + helper(threshold, x-1, y, visit) + helper(threshold, x, y+1, visit) + helper(threshold, x, y-1, visit);
        return c;
    }
    
    int getSum(int a){//计算行坐标或列坐标的数位之和
        int sum = 0;
        while(a){//每个位的和
            sum += a%10;//取最低位
            a /= 10;//右移一位
        }
        return sum;
    }
};

剪绳子

参考:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?f=discussion

明显的动态规划题,所以直接找规律

所以找规律,让绳子有尽可能多的3,当绳子剩1,拿出一个3,变成2*2>3*1;当绳子剩2,直接输出就可。

起始条件:绳子长n = 2,1和1,return 1

                  绳子长n= 3,1和2,return 2

链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?f=discussion
来源:牛客网

/**
 * 题目分析:
 * 先举几个例子,可以看出规律来。
 * 4 : 2*2
 * 5 : 2*3
 * 6 : 3*3
 * 7 : 2*2*3 或者4*3
 * 8 : 2*3*3
 * 9 : 3*3*3
 * 10:2*2*3*3 或者4*3*3
 * 11:2*3*3*3
 * 12:3*3*3*3
 * 13:2*2*3*3*3 或者4*3*3*3
 *
 * 下面是分析:
 * 首先判断k[0]到k[m]可能有哪些数字,实际上只可能是2或者3。
 * 当然也可能有4,但是4=2*2,我们就简单些不考虑了。
 * 5<2*3,6<3*3,比6更大的数字我们就更不用考虑了,肯定要继续分。
 * 其次看2和3的数量,2的数量肯定小于3个,为什么呢?因为2*2*2<3*3,那么题目就简单了。
 * 直接用n除以3,根据得到的余数判断是一个2还是两个2还是没有2就行了。
 * 由于题目规定m>1,所以2只能是1*1,3只能是2*1,这两个特殊情况直接返回就行了。
 *
 * 乘方运算的复杂度为:O(log n),用动态规划来做会耗时比较多。
 */
long long n_max_3(long long n) {
    if (n == 2) {
        return 1;
    }
    if (n == 3) {
        return 2;
    }
    long long x = n % 3;
    long long y = n / 3;
    if (x == 0) {
        return pow(3, y);
    } else if (x == 1) {
        return 2 * 2 * (long long) pow(3, y - 1);
    } else {
        return 2 * (long long) pow(3, y);
    }
}
 
//给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
//
//输入描述:
//输入一个数n,意义见题面。(2 <= n <= 100)
//
//
//输出描述:
//输出答案。
//示例1
//输入
//8
//输出
//18
int main() {
    long long n = 0;
    cin >> n;
    cout << n_max_3(n) << endl;
    return 0;
}

字符流中第一个不重复的字符

参考:https://www.cnblogs.com/silentteller/p/12098395.html

哈希表:用一个关联型容器map来存储,这样空间复杂度为O(n),然后每次都遍历map获取第一个不重复的字符,时间复杂度也为O(n)。

class Solution
{
public:
  //Insert one char from stringstream
    void Insert(char ch)
    {
        res += ch;
        m[ch] ++;//使用map将字符流中的每一个字符出现的次数记录下来
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {
        for(auto i:res){
            //按字符流的顺序查找在map中出现的次数,如果为1,返回该字符即可。
            if(m[i] == 1)
                return i;
        }
        return '#';//【易错】
    }
private:
    string res = "";
    map<char, int> m;//哈希表
};

或者 直接把字符转成ASCII码了

链接:https://www.nowcoder.com/questionTerminal/00de97733b8e4f97a3fb5c680ee10720?f=discussion
来源:牛客网

class Solution
{
public:
  //Insert one char from stringstream
    string s;
    char hash[256]={0};
    void Insert(char ch)
    {
        s+=ch;
        hash[ch]++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {
         
        int size=s.size();
        for(int i=0;i<size;++i)
        {
            if(hash[s[i]]==1)
                return s[i];
        }
        return '#';
    }
 
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值