首页 > 其他分享 >day16

day16

时间:2022-11-10 20:34:23浏览次数:40  
标签:right string int day16 数组 left size

[0344.反转字符串]

class Solution {
public:
    void reverseString(vector<char>& s) {
        int left = 0;
        int right = s.size() - 1;
        while (left < right) {
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
    }
};
  • 这道题 确实简单 只要想到链表反转 用到双指针法 那么这道 数组反转 比链表反转 更简单 这么简单的题 确实几分钟就写出来了 但是要注意以下几点
  • 一是 代码过于冗余
class Solution {
public:
    void reverseString(vector<char>& s) {
        for (int left = 0, int right = s.size() - 1; left <= s.size()/2; left++, right--) {
            swap(s[left], s[right]);
        }
    }
};
    • 自己动手写了同标准答案类似的代码 有以下几点错误
      1. for循环里的left right 只定义一次就够了
      2. left取值范围问题 假设总长是5 那么left取到2就可以 所以s.size()/2没错 不用额外+1或-1 但是注意注意!!!!left默认是从0开始取值的 数组下标就是这样默认规定的 所以 应该是left < s.size()/2 而不是left <= s.size()/2
  • 二是 库函数的调用问题

    • 原则是 如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。 毕竟面试官一定不是考察你对库函数的熟悉程度 ;

      如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。

    • 例如本题 不可以用reverse函数 但可以用swap函数

  • 三是 动手写代码 竟然遇到了这样一个问题:现在写完代码 才知道 哦 不论是 整形数组 还是字符数组 双指针法 我都是设置指针 用来指向数组下标的 那么数组下标 不论数组是存放的什么类型的变量 数组下标都是整形吧 那么我设置的left right 都是int 也就是说 ·int left = 0; 而我刚开始敲代码时 还想着 既然是字符数组 那么指针应该是指向字符的 那么我应该设置成字符类型的指针 那么char *left = 0; !!!要注意 指向字符类型的指针 是要设置成字符指针 但我们这里是数组 虽然我们叫它双指针法 但这是一个总体 概括性概念 在数组里 双指针 具体表现形式 就是 “双下标”了 下标都是整形 所以就设置成int left = 0这样的 那么如果在 链表里 双指针 具体表现形式 就是“结点指针” 故而设置成ListNode *p这样的

[0541.反转字符串II]

class Solution {
public:
    void rev(string s, int k, int left, int right) {
        for (; left < k; left++, right-- ) {
            swap(s[left], s[right]);
        }
    }
    string reverseStr(string s, int k) {
        int left = 0;
        for(int i = 0; i < s.size()/(2 * k); i++) {
            int right = left + k - 1;
            rev(s, k, left, right);
            left += 2 * k;
        }
        return s;
    }
};
  • 对比了标准答案 错误地方主要两处 分别是rev函数定义语句不正确 二是主函数reverseStr里面没有判断剩下字符串长度不够2k的两种情况 下的反转
  • rev函数 的改正(还没看思路 只是对比了 一些语句) 以下均为正确搭配!!!!
    • void reverseString(vector<char>& s, int left, int right) //无返回类型 输入参数为字符数组取地址
    • void reverseString(string& s, int left, int right) //无返回类型 输入参数为字符串型取地址
    • string reverseStr(string s, int left, int right) //返回类型是string型 输入参数string型
  • reverseStr函数的改正 剩下字符串长度可表示为s.size() - left 那么分情况就好 !!!注意这里考虑长度 就不要考虑下标了 只要验证了长度s.size()=7的话 left=2*k=2 * 2 = 4的话 那么相减=3 用3和真实数出来剩余字符串长度确实是3 相比 一样! 那么就不需要再考虑什么s.size()-1或者+1 < 或者<=了
class Solution {
public:
    void rev(string &s, int left, int right) {
        for (; left < right; left++, right-- ) {
            swap(s[left], s[right]);
        }
    }
    string reverseStr(string s, int k) {
        int left = 0;
        for(int i = 0; i < s.size()/(2 * k); i++) {
            int right = left + k - 1;
            rev(s, left, right);
            left += 2 * k;
        }
        if (s.size() - left < k) {
                rev(s, left, s.size() - 1);
            }
        if ((s.size() - left < 2 * k) && (s.size() - left >= k)) {
                rev(s, left, left + k - 1);
            }
        return s;
    }
};
  • 看了卡哥的 确实比我简单一些 因为他把三个情况(剩余长度 要么大于2k 要么在k和2k之间 要么小于k)中的两种情况(前两种) 合二为一了 那么
class Solution {
public:
    string rev(string &s, int left, int right) {
        for (; left < right; left++, right-- ) {
            swap(s[left], s[right]);
        }
        return s;
    }
    string reverseStr(string s, int k) {
        int left = 0;
        for(int i = 0; i < s.size(); i+= (2 * k)) {
            if (s.size() - left < k) {
                rev(s, left, s.size() - 1);
                break;
            }
            rev(s, left, left + k - 1);
            left += 2 * k;
        }
        return s;
    }
};
  • 这个是可以 运行成功的
    • 与卡哥的区别在于 我的 是把长度少于k个的情况 先写 卡哥是后写 先写的话要记得break 因为后面就不需要再循环了(见上面代码) 后写的话要记得continue 因为后面还需要再继续循环的 (见下面卡哥代码)
    • 此外 这个思路 相比于我的最开始的思路 有一个区别是for循环 虽然这两个for循环是等价的 但明显卡哥的(也就是我后来的这个for循环)更简洁些 因为 i就可以直接取每次的left值 那么 相比于 i只是单独负责控制次数 还需要再额外shezhileft值来说 就更简便些 !!!注意 这里i就是每次不再是i++; 而应该是i += (2 * k); 这一点也使我没有想到的写法
class Solution {
public:
    void reverse(string& s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += (2 * k)) {
            // 1. 每隔 2k 个字符的前 k 个字符进行反转
            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
            if (i + k <= s.size()) {
                reverse(s, i, i + k - 1);
                continue;
            }
            // 3. 剩余字符少于 k 个,则将剩余字符全部反转。
            reverse(s, i, s.size() - 1);
        }
        return s;
    }
};

[剑指Offer05.替换空格]

  • 我的思路:字符串》》1.》》数组》》2.》》查找空格 并赋值20%》》》》结束? 但存在诸多问题
  1. 字符串 如何转化为 数组? 两者又有什么区别?

    • 首先 知道了两者有什么区别 那么 “所谓的转换方法”就显而易见了

      • 字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。

        在C语言中,把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。

        例如这段代码:

        char a[5] = "asd";
        for (int i = 0; a[i] != '\0'; i++) {
        }
        

        在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用'\0'来判断是否结束。

        例如这段代码:

        string a = "asd";
        for (int i = 0; i < a.size(); i++) {
        }
        

        那么vector< char > 和 string 又有什么区别呢?

        其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。

        所以想处理字符串,我们还是会定义一个string类型

      • 简而言之 字符串string 是特殊的字符数组char a[] 。 它不仅能被当成数组一样 按下标访问每个元素 还有数组没有的函数 方便操作。

    • 那么 既然字符串 都可以按下表 来访问每个字符元素 也就不需要 转化为数组

  2. 但 在查找并赋值前 这里有一个问题需要注意 就是不同类型的元素所需空间大小是不同的

    • 如果 是整型数组 那么要求把所有元素值为1的替换为目标值3 直接找到并赋值就好了
    • 但 这里是字符串 待替换字符是空格字符 占一个字节 而目标字符是20%占两个字符 因此不能直接 像之前一样 找到并赋值 而是要 先扩容
  3. 关于 查找并赋值

    • 常规思路 两层for循环 即指针从前往后
    • 优化版本 即指针从后往前 可使得后面的元素 一次性把位置移动到位 并且不影响前面的元素 而如果从前往后 前面的移动会影响后面的元素位置 每次循环都会多做一些不能一步到位的无用功
  4. 分析了半天 其实就是 基础语法和语句表达问题太多 导致看了思路也不能写出代码

class Solution {
public:
    string replaceSpace(string s) {
        int countSpace = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == ' ') {
                countSpace++;
            }
        }
        int left = s.size() - 1;
        s.resize(s.size() + countSpace * 2);  //扩宽数组长度的函数resize()
        int right = s.size() - 1;
        while (left < right) {
            if (s[left] == ' ') {
                s[right] = '0';
                s[right-1] = '2';
                s[right-2] = '%';
                left--;
                right = right - 3;
                continue;
            }
            s[right] = s[left];
            left--;
            right--;
        }
        return s;
    }
};
  • resize()函数
  • 卡哥 没用while循环 用的是for循环
class Solution {
public:
    string replaceSpace(string s) {
        int count = 0; // 统计空格的个数
        int sOldSize = s.size();
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == ' ') {
                count++;
            }
        }
        // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
        s.resize(s.size() + count * 2);
        int sNewSize = s.size();
        // 从后先前将空格替换为"%20"
        for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
            if (s[j] != ' ') {
                s[i] = s[j];
            } else {
                s[i] = '0';
                s[i - 1] = '2';
                s[i - 2] = '%';
                i -= 2;
            }
        }
        return s;
    }
};
  • 看来我已经会用continue语句了

明天继续:)

标签:right,string,int,day16,数组,left,size
From: https://www.cnblogs.com/deservee/p/16878648.html

相关文章

  • 牛客java选择题每日打卡Day16
    牛客java选择题每日打卡Day16......
  • 代码随想录Day16
    二叉树的层序遍历:LeetCode102 给你一个二叉树,请你返回其按层序遍历得到的节点值。(即逐层地,从左到右访问所有节点)。  思路:如果我们用树形结构去实现层序遍历,3......
  • day16 运动(上)
    概述:运动(动画),就是操作对应的dom元素发生变化,(这个变化要持续多次(修改样式)),每次间隔的时间是你肉眼察觉不到的(时间比较短).当到达目标位......
  • day16 正则表达式 & 反射 & Java内存模型(JMM)
    day16class1)获取一个类的所有信息(变量、方法、构造方法)2)创建类对象newInstance()Field1)访问变量或给变量赋值Method1)执行具体类对象的指定方法3.Method(获取方法对......
  • 《剑指offer》day16
    把数组排成最小的数题目描述思路本题是遇到的第一道自定义排序的题这类题目关键是要理清排序规则,比如本题中"30"+"3"<"3"+"30",所以"30"<"3"字符串化+插入排序将......
  • java_day16
    Java基础Java集合框架Map接口用于存储任意键值对key-value键:无序、无下标、不允许重复值:无序、无下标、运行重复方法put(key,value)将对象存入到集合中,关联键......
  • day16异常以及生成器
    目录今日内容详细异常常见类型异常处理语法结构异常处理补充异常处理实战应用生成器对象课堂练习yield冷门用法生成器表达式今日内容详细异常常见类型AttributeError......
  • Python学习路程——Day16
    Python学习路程——Day16异常常见类型'''SyntaxErrorNameErrorIndexErrorKeyErrorIndentationError......'''1、SyntaxError三种SyntaxError:invalidsy......
  • day16 异常处理生成器
    day16异常处理生成器今日内容概要异常处理异常处理实战应用生成器对象生成器对象实现range方法生成器表达式今日内容详细一、异常处理1.异常常见类型Synt......
  • 进入python的世界_day16_python基础——异常捕获的处理、生成器对象、生成器表达式
    一、异常捕获1.错误类型语法错误>>>syntaxerror名字错误>>>namerror索引错误>>>Indexerror缩进错误>>>indentationerror等等......2.异常处理语法结构1.语法结......