数据结构基础训练
一、数组
1.1集合
- 定义:由一个或多个确定的元素构成的整体
- 特点:
- 元素类型不一定相同
- 无序性
1.2列表
- 定义:是一种数据项构成的有限序列,即按照一定的线性顺序,排列而成的数据项的集合
- 特点:
- 元素类型不一定相同
- 有序性
- 长度可变
- 常见表现形式
- 数组
- 链表
- 堆
- 栈
1.3数组
- 定义:数组是列表的实现方式之一
- 宏观区分列表与数组
- 列表不具有索引,而数组具有索引用来标识每项数据在列表中的位置
- 数组中的元素在内存中是连续存储的,而列表中的元素可以不连续
1.4总结
一句话总结:集合是爸爸,列表是儿子,数组是孙子。
1.5寻找数组的中心索引(LeetCodeQ1)
- C++实现
class Solution {
public:
int pivotIndex(vector<int>& nums) {
/*目标:寻求一个数组的中心下标
* 1.中心下标是指该下标左边的元素之和与与右边元素的之和相等
* 2.注意:中心下标可以首元素或者或者末元素
* */
/*思路
* 1.从左向右遍历元素
* 2.只需记录一次左边元素之和与右边元素之和
* 3.在之后的遍历中,左边元素进行累加,右边元素累减,直到找到第一个中心下标才停止
* */
if (nums.empty()) return -1;
int left = 0,right = 0;
right=accumulate(nums.begin(), nums.end(), 0);
right = right - nums[0];
for (int i = 0,length = nums.size(); i < length; ++i) {
if (left == right) return i;
left += nums[i];
right -= nums[i+1];
}
return -1;
}
};
- 最好战绩
二、二维数组
2.1定义
- 二维数组是一种结构特殊的数组,数组中的每一个元素都变成了一个一维数组
2.2特点
- 本质依然是一个一维数组,内部的一维数组的索引依然从0开始
- 经常用来处理矩阵相关的问题
- 矩阵旋转
- 对角线遍历
- 对子矩阵的操作
2.3旋转矩阵(LeetCodeQ2)
-
C++实现
-
class Solution { public: void rotate(vector<vector<int>>& matrix) { /*目标 将一个N × N矩阵顺时针旋转90度 * 1.要求不占用额外的存储空间 * */ /*思路 *1.进行由外向内的旋转变换,让一个元素腾空,后面的元素才可以跳进来 *2.用temp作为中间容器 * */ if (matrix.size() == 1) matrix = matrix; for (int j = 0; j < (matrix.size()%2 == 0?matrix.size()/2:matrix.size()+1/2); ++j) { for (int i = 0,count = (matrix.size()-2*j)-1,time=(matrix.size()-1); i < count; ++i) { int temp = 0; temp = matrix[j][i+j]; matrix[j][i+j] = matrix[time-i-j][j]; matrix[time-i-j][j] = matrix[time-j][time-i-j]; matrix[time-j][time-i-j] = matrix[i+j][time-j]; matrix[i+j][time-j] = temp; } } } };
-
-
最好战绩
三、字符串
3.1定义
- 字符串是由零个或多个字符组成的有限序列。一般记为 s = a1a2…an。它是编程语言中表示文本的数据类型。
3.2特点
- 字符串的操作对象大多是字符串整体以及其子串
- 字符串操作比其他数据类型更加复杂
3.3字符串的比较函数
- 用"=="对字符串进行比较
- 取决于所用语言是否支持运算符重载
- C++支持
- Java不支持
- 取决于所用语言是否支持运算符重载
3.4字符串的连接
- 不同的语言中,字符串的可变性是不同的
- C++中字符串是可变的
- Java和Python中字符串是不可变的
- 在字符串不可变的语言中,对字符串进行连接操作会对性能产生影响
- 解决方法
- 使用
toCharArray
将其转换为字符数组 - 使用一些其他的数据结构,如
StringBuilder
- 使用
- 解决方法
3.5最长公共前缀(LeetCodeQ3)
-
class Solution { public: string longestCommonPrefix(vector<string>& strs) { int min_length = 0; int min_index = 0; if (strs.size() == 0) return ""; if (strs.size() == 1) return strs[0]; min_length = strs[0].length(); for (int i = 0,length = strs.size(); i < length-1; ++i) { if (min_length>strs[i+1].length()) { min_length = strs[i+1].length(); min_index = i+1; } } string str = strs[min_index]; if (min_length == 0) return ""; for (int i = 0; i < strs.size(); ++i) { for (int j = 0; j < strs.size(); ++j) { if (str != strs[j].substr(0,min_length)) { str = strs[min_index].erase(min_length-1); min_length = min_length - 1; i = 0; if (min_length == 0) return ""; } } } return str; } };
四、双指针技巧
4.1定义
- 通常,我们只需要一个指针进行迭代,即从数组中的第一个元素开始,最后一个元素结束。然而,有时我们会使用两个指针进行迭代。
4.2应用场景
- 反转数组中的元素
- 数组排序
4.3反转字符串(LeetCodeQ4)
-
class Solution { public: void reverseString(vector<char>& s) { /*目标:反转字符串 * */ /*思路:利用双指针 * */ int length = s.size(); int i = 0; int j = length-1; int temp = 0; for (int k = 0; k < length; ++k) { temp = s[i]; s[i] = s[j]; s[j] = temp; i+=1; j-=1; if (i == j || i - j == 1) break; } } };
-
最好战绩