数据结构4:数组与字符串

1.数组

1.1 知识点

  1. List item
  2. 动态数组vector的使用
  3. 双指针技巧
    1)首尾双指针用于排序等任务,处理效率更高
    2)快慢双指针用于空间受限制时:一个用于迭代,而第二个指针总是指向下一次添加的位置。

1.2 题目类型总结

  • 查找索引,如两数之和
  • 寻找特殊数字
  • 反转
  • 排序
  • 二维数组之花式引用与更改顺序输出

1.2 二维数组1:对角线遍历

好难好难,一脸懵逼.
以对角线入手进行观察:

  • 奇数行对角线是往上的,在不遇到上边界时行列的变化为(-1,1),遇到上边界时,变化为(0,1);在遇到矩阵角点时,变化为(1,0)
  • 偶数行对角线是往下的,不遇到左边界时行列的变化为(1,-1),遇到左边界时,变化为(1,0),遇到下边界时,变化为(0,1)
    遇到任何边界时将切换到下一条对角线,k值转换;并处理边界即可
    vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return {};
        // 矩阵行列;k用于控制对角线行数的的奇偶
        int m = matrix.size(), n = matrix[0].size(), r = 0, c = 0, k = 0;
        vector<int> res(m * n);//结果
        vector<vector<int>> dirs{{-1,1}, {1,-1}};
        for (int i = 0; i < m * n; ++i) {
            res[i] = matrix[r][c];
            r += dirs[k][0];
            c += dirs[k][1];
            if (r >= m) {r = m - 1; c += 2; k = 1 - k;}//遇到下边界
            if (c >= n) {c = n - 1; r += 2; k = 1 - k;}//遇到右边界
            if (r < 0) {r = 0; k = 1 - k;} //遇到上边界
            if (c < 0) {c = 0; k = 1 - k;}//上到左边界
        }
        return res;
    }

1.3 二维数组2:螺旋数组

想想一下你在开车,碰到指示牌就转向…你遇到指示牌后必须调整该指示牌的下一个位置。
还需注意:当列数大于行数的时候,可能会遇到错误的转向,比如3*5的矩阵,在1,1位置会错误转上。
因而采用pair数组来记录当前的方向,只有当当前方向和路标条件吻合顺时针走法时才做出相应调整。
over!

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> result;
        if(matrix.size()<1) return result;

        int m = matrix.size();//行数
        int n = matrix[0].size();//列数

        // 四块指示牌
        pair<int,int> right(1,0);
        pair<int,int> down(0,n-1);
        pair<int,int> left(m-1,n-1);
        pair<int,int> up(m-1,0);
        pair<int,int> velocity(0,1);//速度
        enum flag{_Left,_Right,_Up,_Down};

        pair<int,int> coor(0,0);//当前坐标
        flag last_flag(_Right);//当前状态
        for(int i=0;i<m*n;i++){
            int ele = matrix[coor.first][coor.second];
            result.push_back(ele);
            // 遇到拐点响应的改变速度,否则不变
            if(coor==down && last_flag==_Right){
                velocity= make_pair(1,0);
                down.first = coor.first+1;
                down.second = coor.second-1;
                last_flag = _Down;
            }else if(coor==left && last_flag==_Down){
                velocity= make_pair(0,-1);
                left.first = coor.first-1;
                left.second = coor.second-1;
                last_flag = _Left;
            }else if(coor==up && last_flag==_Left){
                velocity= make_pair(-1,0);
                up.first = coor.first-1;
                up.second = coor.second+1;
                last_flag = _Up;
            }else if( coor==right && last_flag==_Up){
                velocity= make_pair(0,1);
                right.first = coor.first+1;
                right.second = coor.second+1;
                last_flag= _Right;
            }

            coor.first += velocity.first;
            coor.second += velocity.second;
        }

        return result;
    }
};

1.4 二维数组3:杨辉三角1

写到这里感觉自己的做题方式有问题,经常陷入个人思考,而现在段位还比较低…所以感觉挺浪费时间的,毕竟不久也容易忘记。不如先参考别人的思路,然后自己写代码。以后再温习温习。
言归正传,这题就找规律,第i行具有i个数,并且每一行都是对称的,因而可以利用双指针进行优化。
res[i][j]=res[i-1][j-1]+res[i-1][j];注意i和j的定义和数组边界即可。

    vector<vector<int>> generate(int numRows) {
        vector<vector<int> >  result;
        // 第i行具有i个数
        for(int i=0;i<numRows;i++){
            vector<int> rowTemp(i+1,1);
            if(i>1){
                for(int p=1,q=i-1;p<=q;p++,q--){
                    rowTemp[p] = result[i-1][p-1]+result[i-1][p];//上一行的对应下标的数和下标减一的数之和
                    rowTemp[q] = result[i-1][p-1]+result[i-1][p];//两边对称
                }
            }
            result.push_back(rowTemp);
        }
        
        return result;
    }

2.字符串

2.1 知识点

  • 字符串string
    学问很多,比如子串、比较还有和数字字符串的处理,有时间得专门总结一下数字和字符的转换。

字符串与数字的转换

参考链接:字符串与数字的转换

// 字符串与数字的转换
// Created by wbzhang on 2020/3/12.
// 摘自博客:https://blog.csdn.net/u011251945/article/details/81609821?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <sec_api/string_s.h>

using namespace std;

int main(){
     1- 数字转字符串
    int num =12;
    char numS[10];
    // 1.1 通过内存拷贝的方式将int转化为字符串
    sprintf_s(numS,"%d",num);
    cout<<"numS:"<< numS <<endl;

    // 1.2 字符串的字符流转换
    int n0 = 101;
    string str1;
    stringstream ss;
    ss << n0;
    ss >> str1;
    cout<<"str1:"<< str1 <<endl;

    // 或者 用ostringstream
    string str0;
    ostringstream os;
    os << n0;
    str0 = os.str();
    cout<<"str0:"<< str0 <<endl;


    //1.3 c_str
    string str2 = "123";
    char *dest = new char [10];
    strcpy_s(dest, 5, str2.c_str());
//    cout<"dest:" << (*dest) <<endl;

     2-字符串转数字
    string str3 = "101";
    //c++11中字符串转int
    int m = stoi(str3); // string to int
    //各种数字类型转字符串int,float,long,double等
    string str4 = to_string(m); //数字转字符串
    
     3- 将字符串转为各种进制格式,取决于string的表达方式
    cout << "16进制: " << stoi(str3, nullptr,16) <<" "<<"2进制:"<<stoi(str3, nullptr, 2) << endl;
    cout << "10进制:" << stoi(str3, nullptr, 10) << " " << "8进制:" << stoi(str3, nullptr, 8) << endl;
    
     4- c语言中的字符串转数字
    // 我记得应该还有wtoi这些,w表示宽字符,学问挺多的
    
    //c语言中字符串转float
    float n = atof(str3.c_str()); // ascii to float
    //c库中字符串转long
    long n1 = atol(str3.c_str()); // ascii to long
    //c库中字符串转int
    int n2 = atoi(str3.c_str());
    
     5-字母大小写转换与ascii
    string str5 = "nihao";
    //小写字母转大写字母
    for (int i = 0; i < str5.size(); i++)
        str5[i] = toupper(str5[i]);
    //小写字母转大写字母
    for (int i = 0; i < str5.size(); i++)
        str5[i] = tolower(str5[i]);
    //数字转ASCII
    int n3 = 65;
    char c = toascii(n3);
    system("pause");

    return 0;
}

还有通过ascii进行字符和整数之间的转换

// 单个字符转数字
char s='9';
int numS = int(s-'0'); // 0的ASCII码是48

//单个数字转字符
int num = 9;
char numStr = num+'0';

常见ASCII码

  • 0-NUL 空字符
  • 13-CR 回车键
  • 32-space 空格键
  • 48- 字符0
  • 57-字符9
  • 65-大写字母A
  • 90-大写字母Z
  • 97-小写字母a
  • 122-小写字母z
  • 127-删除

2.2 最长公共子串

很简单的题,但是我的做法太繁琐了,主要我没用substr。还是来学习一下大神的解答~

解法1:这个第一行好评!这种写法舒适啊。substr(ind,length)作切片当索引加长度超出数组长度时,会返回索引到数组最后一个元素,而不必担心越界。没啥可说的了…

string longestCommonPrefix(vector<string>& strs) {
    string r = strs.size() ? strs[0] : "";
    for(auto s: strs){
        while(s.substr(0, r.size()) != r){
            r = r.substr(0, r.size() - 1);
            if(r == "") return r;
        }
    }
    return r;
}

解法2:第j(j>1)个字符串的第i个字符与第一个字符串的的第i个字符不同时,返回此时对第一个字符串的切片。

  string longestCommonPrefix(vector<string>& strs) {
            if(strs.size()==0)          return "";

            for(int i=0;i<strs[0].size();i++)
                for(int j=1;j<strs.size();j++)   
                    if(strs[j][i]!=strs[0][i])           
                        return strs[0].substr(0,i);        
                        //substr取前i个元素,因为索引i对应的是第i+1个元素不是共有的,所以前i个是共有前缀
            return strs[0];
    }

2.3 长度最小的数组

在这里插入图片描述

题解:
1)双指针法:取首尾指针p和q,如果p与q之间的总和<s;返回0
否则,比较p和q的大小,若*p>=*q,则q–;否则p++;
直到p==q或者两者之间的和<s时,返回q-p


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值