一个不错的网站 .
Reference - C++ Reference (cplusplus.com)http://www.cplusplus.com/reference/
摘自
感谢大佬carl的分享。
数组在内存中的存储方式:
数组是存放在连续内存空间上的相同类型数据的集合。
数组可以方便的通过下标索引的方式获取到下标下对应的数据。
注意:数组下标都是从0开始的;数组内存空间的地址是连续的。
正是因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。
[连续地址的间距是元素大小。一般来说,int占4字节,4byte.(1字节=8位(1 byte = 8bit))]
在C++中,要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
数组的元素是不能删的,只能覆盖。
二维数组在内存的地址空间是连续的!
最近在看深入理解计算机系统这本书,上面提到了在32位机器和64机器中int类型都占用4个字节。后来,查了The C Programming language这本书,里面有一句话是这样的:Each compiler is free to choose appropriate sizes for its own hardware, subject only to the restriction that shorts and ints are at least 16bits, longs are at least 32bits, and short is no longer than int, which is no longer than long.意思大致是编译器可以根据自身硬件来选择合适的大小,但是需要满足约束:short和int型至少为16位,long型至少为32位,并且short型长度不能超过int型,而int型不能超过long型。这即是说各个类型的变量长度是由编译器来决定的,而当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节(例如,GCC)。下面列举在GCC编译器下32位机器和64位机器各个类型变量所占字节数:
C类型 | 32位机器 | 64位机器 |
char | 1 | 1 |
short int | 2 | 2 |
int | 4 | 4 |
long int | 4 | 8 |
long long int | 8 | 8 |
char* | 4 | 8 |
float | 4 | 4 |
double | 8 | 8 |
需要说明一下的是指针类型存储的是所指向变量的地址,所以32位机器只需要32bit,而64位机器需要64bit。 ---摘自
int类型究竟占几个字节_Charles的技术博客_51CTO博客_int类型占用几个字节_一个int类型占多少个字节https://blog.51cto.com/charlesxie/939680
补充总结:
经过询问,网上查找以及测试,发现 数据类型占内存的位数实际上与操作系统的位数和编译器(不同编译器支持的位数可能有所不同)都有关,具体某种数据类型占字节数得编译器根据操作系统位数两者之间进行协调好后分配内存大小。具体在使用的时候如想知道具体占内存的位数通过sizeof(int)可以得到准确的答案。 ---摘自
int类型究竟占几个字节_海神号的博客-CSDN博客_int 占几个字节https://blog.csdn.net/weixin_42339460/article/details/81455103------以上是简单的数组知识,接下来是刷题。
简单的排序题
506-相对名次-力扣https://leetcode-cn.com/problems/relative-ranks/solution/官方题解是这样的。
class Solution {
public:
vector<string> findRelativeRanks(vector<int>& score) {
int n = score.size();
string desc[3] = {"Gold Medal", "Silver Medal", "Bronze Medal"};
vector<pair<int, int>> arr;
for (int i = 0; i < n; ++i) {
arr.emplace_back(make_pair(-score[i], i));
}
sort(arr.begin(), arr.end());
vector<string> ans(n);
for (int i = 0; i < n; ++i) {
if (i >= 3) {
ans[arr[i].second] = to_string(i + 1);
} else {
ans[arr[i].second] = desc[i];
}
}
return ans;
}
};
我自己对sort、pair<int,int>排序这块忘记了。这位大佬总结的就很好。
C++对一组pair数据进行排序(sort函数的使用) - Hahallo - 博客园 (cnblogs.com)https://www.cnblogs.com/bigyang/p/8590552.htmlsort - C++ Reference (cplusplus.com)提供的例子是
// sort algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::sort
#include <vector> // std::vector
bool myfunction (int i,int j) { return (i<j); }//升序;i>j是降序
struct myclass {
bool operator() (int i,int j) { return (i<j);}//升序;i>j是降序
} myobject;
int main () {
int myints[] = {32,71,12,45,26,80,53,33};
std::vector<int> myvector (myints, myints+8);
// 32 71 12 45 26 80 53 33
// using default comparison (operator <):
std::sort (myvector.begin(), myvector.begin()+4); //开区间
//(12 32 45 71)26 80 53 33
// using function as comp
std::sort (myvector.begin()+4, myvector.end(), myfunction);
// 12 32 45 71(26 33 53 80)
// using object as comp
std::sort (myvector.begin(), myvector.end(), myobject);
//(12 26 32 33 45 53 71 80)
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
有一个朋友问了我一个简单的题
35. 搜索插入位置 - 力扣(LeetCode)https://leetcode-cn.com/problems/search-insert-position/这个写法为什么不对。是因为我这个朋友想当然地把大于号>和小于号<当成镜像对称的了,他觉得:判定出左右界需要缩小的逻辑是对称的。其实不难理解,但是不小心就会搞错
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0,right=nums.size()-1;
int mid = left+(right-left)/2;
int res = nums.size();
while(left<=right){
mid = left+(right-left)/2;
if(nums[mid]==target){//相等
return mid;
}
else if(nums[mid]>target){//
right=mid-1;//右界左移。
}
else{//
left=mid+1;//左界右移。
}
}
return res;
}
};
这个 mid = left+(right-left)/2; 是自动取整了,向下取整,向左靠拢,所以左右的权重是不同的,需要仔细考虑。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0,right=nums.size()-1;
int mid = left+(right-left)/2;
int res = nums.size();
while(left<=right){
mid = left+(right-left)/2;
if(nums[mid]==target){
return mid;
}
else if(nums[mid]>target){//目标值小了,
res=mid;//要注意
right=mid-1;//右界左移。
}
else{//目标值大了
left=mid+1;//左界右移。
}
}
return res;
}
};
如果nums[mid]==target,直接返回mid;
如果是nums[mid]>target,右界缩小,有可能出现"左大于右"的情况,因此在缩小右边界时,用res保存mid,一旦出现"左大于右",则res保存的mid正是最合适的插入位置。
如果是nums[mid]<target,左界缩小,也有可能出现"左大于右"的异常情况。一旦出现“左大于右”,则res初始化的值len就弥补的漏洞:nums里没有合适的位置给target,只能在末位插值。
1034. 边界着色 - 力扣(LeetCode)https://leetcode-cn.com/problems/coloring-a-border/写不出来。。
typedef pair<int, int> pii;
class Solution {
public:
vector<vector<int>> colorBorder(vector<vector<int>>& grid, int row, int col, int color) {
int m = grid.size(), n = grid[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
vector<pii> borders;
int originalColor = grid[row][col];
visited[row][col] = true;
dfs(grid, row, col, visited, borders, originalColor);//找需要改的点
for (auto & [x, y] : borders) {
grid[x][y] = color;//改
}
return grid;
}
void dfs(vector<vector<int>>& grid, int x, int y, vector<vector<bool>> & visited, vector<pii> & borders, int originalColor) {
int m = grid.size(), n = grid[0].size();
bool isBorder = false;
int direc[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};//初始化4个方向
for (int i = 0; i < 4; i++) {//遍历4个方向,
int nx = direc[i][0] + x, ny = direc[i][1] + y;//[x,y]这个点朝某个方向移动一步
if (!(nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == originalColor)) {//如果符合条件
isBorder = true;//这个点在边界。只要有一个方向使得它在边界,则isBorder=true
//到边界就不移动了。
}
else if (!visited[nx][ny]) {//如果这个点不在边界,
visited[nx][ny] = true;//遍历过了
dfs(grid, nx, ny, visited, borders, originalColor);//递归到下一个位置。
}
}
if (isBorder) {//如果在边界
borders.emplace_back(x, y);//则插入。
}
}
};
//----------
typedef pair<int,int> pii;
class Solution {
public:
vector<vector<int>> colorBorder(vector<vector<int>>& grid, int row, int col, int color) {
int m = grid.size(), n = grid[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));
vector<pii> borders;
int originalColor = grid[row][col];
int direc[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
queue<pii> q;
q.emplace(row, col);
visited[row][col] = true;
while (!q.empty()) {
pii & node = q.front();
q.pop();
int x = node.first, y = node.second;
bool isBorder = false;
for (int i = 0; i < 4; i++) {
int nx = direc[i][0] + x, ny = direc[i][1] + y;
if (!(nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == originalColor)) {
isBorder = true;
} else if (!visited[nx][ny]) {
visited[nx][ny] = true;
q.emplace(nx, ny);
}
}
if (isBorder) {
borders.emplace_back(x, y);
}
}
for (auto & [x, y] : borders) {
grid[x][y] = color;
}
return grid;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/coloring-a-border/solution/bian-kuang-zhao-se-by-leetcode-solution-0h5l/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
学习一下:for(auto &[x,y] borders){
//borders是vector<pair<int,int>>.
//使用auto标明一个变量,这个变量永远不会是引用变量。
//使用auto&标明一个变量,这个变量有可能被编译器推导为引用变量。
C++ 中auto与auto&的区别 (详细)_artistkeepmonkey的博客-CSDN博客_c++中autohttps://blog.csdn.net/artistkeepmonkey/article/details/106334555
}
---------------------------------------------------------------------------------------------------------------------------------
b站刷到了 爱学习的饲养员,她发布了很多不错的内容,讲解、图解。所以想把以前的内容补充一下
爱学习的饲养员的个人空间_哔哩哔哩_bilibilihttps://space.bilibili.com/31337561数组:在连续的内存空间中,存储一组相同类型的元素。
访问access | O(1) | 根据第一个元素的地址,和元素所占内存大小,就能直接找到第几个元素的地址,并访问。 |
搜索search | O(N) | 不知道地址,不知道索引,需要从头开始遍历。 |
插入insert | O(N) | 在连续空间插入元素,通常在末位元素后插入元素,(如果末位有足够的空间),然后从前往后传递元素的值,并把目标位置的元素赋值赋目标值。 如果末位没有空间,无法插入元素,就只能再另找一个连续空间,顺次赋值。 |
删除delete | O(N) | 在连续空间删除元素,找到删除元素的位置。当前元素的值由后1个元素赋值,下个元素的值又由下下个元素的值赋值... 数组长度减1 |
特点:适合读;不适合写===>适合读操作多,写操作少的场景。
常用操作:
创建数组、添加元素、访问元素、修改元素、删除元素、遍历数组、查找元素、数组的长度、数组排序。