当前位置:   article > 正文

数据结构(一):数组及面试常考的算法_数据结构常考算法

数据结构常考算法

数据结构是计算机存储、组织数据的方式。一种好的数据结构可以带来更高的运行或者存储效率。数据在内存中是呈线性排列的,但是我们可以使用指针等道具,构造出类似“树形”的复杂结构。下面介绍八个常见的数据结构。

数据结构分为线性数据结构非线性数据结构

线性数据结构包括:数组(Array)、链表(Linked List)、栈(Stack)、队(Queue)。

非线性数据结构包括:树(Tree)、堆(Heap)、散列表(Hashing)、图(Graph)。

一、数组介绍

1、定义

数组是一种线性结构,而且在物理内存中也占据着一块连续空间。数组分为一维数组多维数组两种类型。

2、优缺点及使用场景

优点:访问数据简单。

缺点:添加和删除数据比较耗时间。

使用场景:频繁查询,对存储空间要求不大,很少增加和删除的情况。

3、增删改查

数据访问:由于数据是存储在连续空间内,所以每个数据的内存地址都是通过数据小标算出,所以可以直接访问目标数据。(这叫做“随机访问”)。

数据添加:数据添加需要移动其他数据。首先增加足够的空间,然后把已有的数据一个个移开。

数据删除:如果想要删除数据,也是一样挨个把数据往反方向移动。

4、数组的基本操作

Insert--在指定索引位置插入一个元素。

Get--返回指定索引位置的元素。

Delete--删除指定索引未知的元素。

Size--得到数组所有元素的数量。

二、常考算法

  1. 寻找数组中第二小(大)的元素。

思路:

(1)先定义一个min和second_min,将数组中第一个元素赋值给min,第二个元素赋值个second_min。

(2)判断数组第一个和第二个元素的大小,交换最小值和第二小值。

(3)从数组第3个元素开始遍历,分别与当前最小值min和第二小值second_min比较, 如果当前数组元素小于当前最小值min, 那么当前最小值就是第二最小值;如果当前元素小于第二最小值second_min,那么当前元素就是第二最小值。

  1. // 时间复杂度为O(n)
  2. int SearchSecondMin(int nums[], int length){
  3. int min = nums[0]; //假设数组中第一个元素是最小值
  4. int second_min = nums[1]; //数组中第二个元素是第二小值
  5. if(length < 2 || nums == NULL){
  6. return -1;
  7. }
  8. // 判断数组第一个和第二个元素的大小,交换最小值和第二小值
  9. if( min > second_min){
  10. min = nums[1];
  11. second_min = nums[0];
  12. }
  13. // 从数组第3个元素开始遍历,分别与当前最小值和第二小值比较,
  14. // 如果当前元素小于当前最小值, 那么当前最小值就是第二最小值;如果当前元素小于第二最小值,那么当前元素就是第二最小值.
  15. for(int i = 2; i < length; i++){
  16. if(nums[i] < min){
  17. second_min = min;
  18. min = nums[i];
  19. }
  20. else if (nums[i] < second_min)
  21. {
  22. second_min = nums[i];
  23. }
  24. }
  25. cout<<"数组中第二小的元素为:"<< second_min <<endl;
  26. return second_min;
  27. }
  28. // 类似的,寻找数组中第二大的元素
  29. int SearchSecondBig(int nums[], int length){
  30. int max = nums[0];
  31. int second_max = nums[1];
  32. if(nums == NULL || length < 2){
  33. return -1;
  34. }
  35. if(max < second_max){
  36. max = nums[1];
  37. second_max = nums[0];
  38. }
  39. for (int i = 2; i < length; i++){
  40. if(nums[i] > max){
  41. second_max = max;
  42. max = nums[i];
  43. }
  44. else if (nums[i] > second_max)
  45. {
  46. second_max = nums[i];
  47. }
  48. }
  49. cout<<"数组中第二大的元素为:"<< second_max <<endl;
  50. return second_max;
  51. }
  52. int main(){
  53. int nums[] = {-2,0,4,3,-1};
  54. int length = sizeof(nums) / sizeof(nums[0]);
  55. SearchSecondMin(nums, length);
  56.     SearchSecondBig(nums, length);
  57. return 0;
  58. }

2、找到数组中第一个不重复的出现的整数。

思路:使用两个循环。外部循环逐个遍历元素,内部循环检查元素是否存在多次或不存在。

  1. #include<iostream>
  2. using namespace std;
  3. // 两层for循环
  4. int SearchFirstUnrepeat(int nums[], int length){
  5. int unrepeat;
  6. // 外层循环逐个遍历元素
  7. for(int i = 0; i < length; i++){
  8. int j;
  9. // 内层循环判断元素是否存在多次或不存在
  10. for(j = 0; j < length; j++){
  11. if(i != j && nums[i] == nums[j]){
  12. break;
  13. }
  14. }
  15. if(j == length){ //如果j遍历到最后没有找到重复的元素,就返回当前i对应的元素
  16. unrepeat = nums[i];
  17. return unrepeat; //return跳出循环
  18. }
  19. }
  20. return -1;
  21. }
  22. int main(){
  23. int nums[] = {1,2,1,3,4};
  24. int length = sizeof(nums) / sizeof(nums[0]);
  25. int result = SearchFirstUnrepeat(nums, length);
  26. cout << "数组中第一个不重复的元素是" << result << endl;
  27. }
  1. 合并两个有序数组。

题目:已知两个有序数组,合并两个有序数组,并且要求重复元素只出现一次。如nums1={2,3,3,5,7,8},nums2={3,3,5,8}。合并后数组:nums={2,3,5,7,8}。

思路:

第一步:利用双指针法(快慢指针)去掉两个有序数组中的重复元素(只出现一次)。

第二步:利用双指针法分别指向两个数组,比较两个有序数组的元素。若nums1<nums2,指向nums1的指针+1,若nums2<nums1,指向nums2的指针+1,若nums1==nums2,同时+1。

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<vector>
  4. using namespace std;
  5. //双指针法:去掉数组中重复项
  6. vector<int> removeDuplicates(int nums[], int length){
  7. int fastIndex, slowIndex=0;
  8. vector<int> vint;
  9. for(fastIndex = slowIndex + 1; fastIndex < length; fastIndex++){
  10. //找到了不与nums[slowIndex]的重复的值,则将不重复的值赋值放在slowIndex的后面一位,同时slowIndex的下标后移一位,开始下一个数的重复判断。
  11. if(nums[fastIndex] != nums[slowIndex]){
  12. nums[++slowIndex] = nums[fastIndex];
  13. }
  14. }
  15. for(int i = 0; i < slowIndex + 1; i++){
  16. vint.push_back(nums[i]);
  17. }
  18. return vint;
  19. }
  20. // 合并两个有序数组
  21. void addTwoNums(int a[], int b[], int a_length, int b_length){
  22. // 去掉nums1和nums2里的重复元素(重复元素只算一次)
  23. vector<int> vInt1, vInt2;
  24. vInt1 = removeDuplicates(a, a_length);
  25. vInt2 = removeDuplicates(b, b_length);
  26. cout << "nums1去重后的数组:" ;
  27. for(int i = 0; i < vInt1.size(); i++){
  28. cout << vInt1[i] << " ";
  29. }
  30. cout << endl;
  31. cout << "nums2去重后的数组:" ;
  32. for(int i = 0; i < vInt2.size(); i++){
  33. cout << vInt2[i] << " ";
  34. }
  35. cout<<endl<<"合并nums1与nums2:";
  36. // 合并两个有序数组
  37. vector<int> nums;
  38. int i = 0, j=0;
  39. while((i != vInt1.size()) && (j != vInt2.size())){
  40. if(vInt1[i] == vInt2[j]){
  41. nums.push_back(vInt1[i]);
  42. i++;
  43. j++;
  44. }
  45. else if(vInt1[i] < vInt2[j]){
  46. nums.push_back(vInt1[i]);
  47. i++;
  48. }
  49. else{
  50. nums.push_back(vInt2[j]);
  51. j++;
  52. }
  53. }
  54. for(auto c: nums){
  55. cout << c << " ";
  56. }
  57. }
  58. int main(){
  59. int nums1[] = {2,3,3,5,7,8};
  60. int nums2[] = {3,3,5,8};
  61. int nums1_length = sizeof(nums1) / sizeof(nums1[0]);
  62. int nums2_length = sizeof(nums2) / sizeof(nums2[0]);
  63. addTwoNums(nums1,nums2, nums1_length, nums2_length);
  64. }

4、重新排列数组中的正数和负数。

题目:对数组中的正负数重新排序,使负数排在正数之前。如nums={8, 4, 5, -2, 6, -3, 5},输出nums={-3 -2 5 4 6 8 5}。

思路:采用双指针,使从前往后第i个负数和从后往前第j个正数交换位置。

  1. #include<iostream>
  2. using namespace std;
  3. // 对数组中的正负数重新排序,使负数排在正数之前
  4. void RealignmentNumbers(int nums[], int length){
  5. int i = 0, j = length - 1;
  6. // 采用双指针,规定i指向的数是正数,j指向的数是负数。
  7. while(i != j){
  8. while(nums[i] < 0)
  9. i++;
  10. while(nums[j] > 0)
  11. j--;
  12. if(i == length - 1 || j == 0)
  13. break;
  14. int temp;
  15. temp = nums[i];
  16. nums[i] = nums[j];
  17. nums[j] = temp;
  18. i++;
  19. j--;
  20. }
  21. for(int m = 0; m < length; m++){
  22. cout << nums[m] << " ";
  23. }
  24. }
  25. int main(){
  26. int nums[] = {8, 4, 5, -2, 6, -3, 5};
  27. int length = sizeof(nums) / sizeof(nums[0]);
  28. RealignmentNumbers(nums, length);
  29. return 0;
  30. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/496398
推荐阅读
相关标签
  

闽ICP备14008679号