数组
是一种基本的数据结构,用于按顺序存储元素的集合
。可是元素能够随机存取,由于数组中的每一个元素均可以经过数组索引
来识别。ios
数组能够有一个或多个维度。这里咱们从一维数组
开始,它也被称为线性数组。这里有一个例子:c++
在上面的例子中,数组 A 中有 6 个元素。也就是说,A 的长度是 6 。咱们可使用 A[0] 来表示数组中的第一个元素。所以,A[0] = 6 。相似地,A[1] = 3,A[2] = 8,依此类推。git
数组中的操做编程
让咱们来看看数组的用法:数组
#include <iostream> int main() { // 1. Initialize int a0[5]; int a1[5] = {1, 2, 3}; // other element will be set as the default value // 2. Get Length int size = sizeof(a1) / sizeof(*a1); cout << "The size of a1 is: " << size << endl; // 3. Access Element cout << "The first element is: " << a1[0] << endl; // 4. Iterate all Elements cout << "[Version 1] The contents of a1 are:"; for (int i = 0; i < size; ++i) { cout << " " << a1[i]; } cout << endl; cout << "[Version 2] The contents of a1 are:"; for (int& item: a1) { cout << " " << item; } cout << endl; // 5. Modify Element a1[0] = 4; // 6. Sort sort(a1, a1 + size); }
正如咱们在上一篇文章中提到的,数组具备固定的容量
,咱们须要在初始化时指定数组的大小。有时它会很是不方便并可能形成浪费。数据结构
所以,大多数编程语言都提供内置的动态数组
,它仍然是一个随机存取的列表数据结构,但大小是可变的
。例如,在 C++ 中的 vector
,以及在 Java 中的 ArrayList
。dom
动态数组中的操做编程语言
让咱们来看看动态数组的用法:spa
#include <iostream> int main() { // 1. initialize vector<int> v0; vector<int> v1(5, 0); // 2. make a copy vector<int> v2(v1.begin(), v1.end()); vector<int> v3(v2); // 2. cast an array to a vector int a[5] = {0, 1, 2, 3, 4}; vector<int> v4(a, *(&a + 1)); // 3. get length cout << "The size of v4 is: " << v4.size() << endl; // 4. access element cout << "The first element in v4 is: " << v4[0] << endl; // 5. iterate the vector cout << "[Version 1] The contents of v4 are:"; for (int i = 0; i < v4.size(); ++i) { cout << " " << v4[i]; } cout << endl; cout << "[Version 2] The contents of v4 are:"; for (int& item : v4) { cout << " " << item; } cout << endl; cout << "[Version 3] The contents of v4 are:"; for (auto item = v4.begin(); item != v4.end(); ++item) { cout << " " << *item; } cout << endl; // 6. modify element v4[0] = 5; // 7. sort sort(v4.begin(), v4.end()); // 8. add new element at the end of the vector v4.push_back(-1); // 9. delete the last element v4.pop_back(); }
给定一个整数类型的数组 nums
,请编写一个可以返回数组“中心索引”的方法。3d
咱们是这样定义数组中心索引的:数组中心索引的左侧全部元素相加的和等于右侧全部元素相加的和。
若是数组不存在中心索引,那么咱们应该返回 -1。若是数组有多个中心索引,那么咱们应该返回最靠近左边的那一个。
示例 1:
输入: nums = [1, 7, 3, 6, 5, 6] 输出: 3 解释: 索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。 同时, 3 也是第一个符合要求的中心索引。
示例 2:
输入: nums = [1, 2, 3] 输出: -1 解释: 数组中不存在知足此条件的中心索引。
说明:
nums
的长度范围为 [0, 10000]
。nums[i]
将会是一个范围在 [-1000, 1000]
的整数。class Solution{ public: int pivotIndex(vector<int>& nums){ if(nums.size() == 0) return -1; int sum = accumulate(nums.begin(), nums.end(), 0); int leftSum = 0; for(int i=0; i<nums.size(); i++) if(leftSum == sum-leftSum-nums[i]) return i; else leftSum += nums[i]; return -1; } };
在一个给定的数组nums
中,老是存在一个最大元素 。
查找数组中的最大元素是否至少是数组中每一个其余数字的两倍。
若是是,则返回最大元素的索引,不然返回-1。
示例 1:
输入: nums = [3, 6, 1, 0] 输出: 1 解释: 6是最大的整数, 对于数组中的其余整数, 6大于数组中其余元素的两倍。6的索引是1, 因此咱们返回1.
示例 2:
输入: nums = [1, 2, 3, 4] 输出: -1 解释: 4没有超过3的两倍大, 因此咱们返回 -1.
提示:
nums
的长度范围在[1, 50]
.nums[i]
的整数范围在 [0, 99]
.#include <iostream> #include <vector> using namespace std; /// Linear Scan /// Time Complexity: O(n) /// Space Complexity: O(1) class Solution{ public: int dominantIndex(vector<int>& nums){ int maxNum = *max_element(nums.begin(), nums.end()); int res = -1; for(int i = 0; i< nums.size(); i++) if(nums[i] != maxNum){ if(maxNum < 2*nums[i]) return -1; } else res = i; return res; } };
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每一个元素只存储一个数字。
你能够假设除了整数 0 以外,这个整数不会以零开头。
示例 1:
输入: [1,2,3] 输出: [1,2,4] 解释: 输入数组表示数字 123。
示例 2:
输入: [4,3,2,1] 输出: [4,3,2,2] 解释: 输入数组表示数字 4321。
#include <iostream> #include <vector> using namespace std; /// Ad Hoc /// Time Complexity: O(n) /// Space Complexity: O(1) class Solution{ public: vector<int> plusOne(vector<int>& digits){ digits[digits.size() -1] ++; for(int i=digits.size()-1; i>=1; i--) if(digits[i] == 10){ digits[i] = 0; digits[i-1] ++; } if(digits[0] == 10){ digits[0] = 0; digits.insert(digits.begin(), 1); } return digits; } }
相似于一维数组,二维数组
也是由元素的序列组成。可是这些元素能够排列在矩形网格中而不是直线上。
示例
#include <iostream> template <size_t n, size_t m> void printArray(int (&a)[n][m]) { for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cout << a[i][j] << " "; } cout << endl; } } int main() { cout << "Example I:" << endl; int a[2][5]; printArray(a); cout << "Example II:" << endl; int b[2][5] = {{1, 2, 3}}; printArray(b); cout << "Example III:"<< endl; int c[][5] = {1, 2, 3, 4, 5, 6, 7}; printArray(c); cout << "Example IV:" << endl; int d[][5] = {{1, 2, 3, 4}, {5, 6}, {7}}; printArray(d); }
原理
在一些语言中,多维数组其实是在内部
做为一维数组实现的,而在其余一些语言中,实际上
根本没有多维数组
。
1. C++ 将二维数组存储为一维数组。
下图显示了大小为 M * N 的数组 A 的实际结构:
2. 在Java中,二维数组其实是包含着 M 个元素的一维数组,每一个元素都是包含有 N 个整数的数组。
下图显示了 Java 中二维数组 A 的实际结构:
动态二维数组
与一维动态数组相似,咱们也能够定义动态二维数组。 实际上,它能够只是一个嵌套的动态数组。 你能够本身尝试一下。
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的全部元素,对角线遍历以下图所示。
示例:
输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 输出: [1,2,4,7,5,3,6,8,9]
解释:
说明:
#include <iostream> #include <vector> using namespace std; /// Simulation /// Time Complexity: O(n * m) /// Space Complexity: O(1) class Solution { private: int n, m; public: vector<int> findDiagonalOrder(vector<vector<int>> &matrix) { vector<int> res; n = matrix.size(); if (n == 0) return res; m = matrix[0].size(); int x = 0, y = 0; int nextX, nextY; bool up = true; while (true) { res.push_back(matrix[x][y]); if (up) nextX = x - 1, nextY = y + 1; else nextX = x + 1, nextY = y - 1; if(inArea(nextX, nextY)) x = nextX, y = nextY; else if(up){ if(inArea(x, y+1)) y++; else x++; up = false; } else{ if(inArea(x+1, y)) x++; else y++; up = true; } if(!inArea(x, y)) break; } return res; } private: bool inArea(int x, int y){ return x>=0 && x<n && y >=0 && y<m; } }; void print_vec(const vector<int>& vec){ for(int e: vec) cout << e << " "; cout << endl; } int main(){ vector<vector<int>> matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; print_vec(Solution().findDiagonalOrder(matrix)); return 0; }
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的全部元素。
示例 1:
输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入: [ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12] ] 输出: [1,2,3,4,8,12,11,10,9,5,6,7]
/// Source : https://leetcode.com/problems/spiral-matrix/description/ /// Author : liuyubobobo /// Time : 2018-04-24 #include <iostream> #include <vector> using namespace std; /// Simulation /// Time Complexity: O(n^2) /// Space Complexity: O(n^2) class Solution { private: int d[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; int N, M; public: vector<int> spiralOrder(vector<vector<int>>& matrix) { N = matrix.size(); if(N == 0) return {}; M = matrix[0].size(); if(M == 0) return {}; vector<vector<bool>> visited(N, vector<bool>(M, false)); int curd = 0, curx = 0, cury = 0; vector<int> res; while(res.size() < N * M){ if(!visited[curx][cury]) { res.push_back(matrix[curx][cury]); visited[curx][cury] = true; } int nextx = curx + d[curd][0]; int nexty = cury + d[curd][1]; if(inArea(nextx, nexty) && !visited[nextx][nexty]){ curx = nextx; cury = nexty; } else curd = (curd + 1) % 4; } return res; } private: bool inArea(int x, int y){ return x >= 0 && x < N && y >= 0 && y < M; } }; void print_vec(const vector<int>& vec){ for(int e: vec) cout << e << " "; cout << endl; } int main() { vector<vector<int>> matrix1 = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; print_vec(Solution().spiralOrder(matrix1)); return 0; }
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在杨辉三角中,每一个数是它左上方和右上方的数的和。
示例:
输入: 5 输出: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]
#include <iostream> #include <vector> using namespace std; /// Simulation (Dynamic Programming) /// Time Complexity: O(n^2) /// Space Complexity: O(1) class Solution{ public: vector<vector<int>> generate(int numRows){ vector<vector<int>> res; if(numRows <= 0) return res; res.push_back({1}); for(int i=1; i<numRows; i++){ vector<int> row; row.push_back(1); for(int j=1; j<i; j++) row.push_back(res[i-1][j-1]+res[i-1][j]); row.push_back(1); res.push_back(row); } return res; } };