算法实战(数组篇)

数组篇

  • 26.删除有序数组中的重复项
    • 题目详情
    • 题解
  • 27. 移除元素
    • 题解
  • 35. 搜索插入位置
    • 题目详情
    • 题解
  • 66. 加1
    • 题目详情
    • 题解
  • 88. 合并两个有序数组
    • 题目详情
    • 题解
  • 108. 将有序数组转换为二叉搜索树
    • 题目详情
    • 题解
    • 注意
  • 118. 杨辉三角
    • 题目详情
    • 题解
  • 119. 杨辉三角 II
    • 题目详情
    • 题解
  • 136. 只出现一次的数字
    • 题目详情
    • 题解
  • 169. 多数元素
    • 题目详情
    • 题解
    • 摩尔投票算法
      • 摩尔投票算法的优点
      • 摩尔投票算法的缺点

26.删除有序数组中的重复项

题目详情

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。

题解

int removeDuplicates(int* nums, int numsSize) {
    int i=0,count;
    for(int j=1;j<numsSize;j++){
        if(nums[i]!=nums[j])
            nums[++i]=nums[j];
    }
    count=i+1; // i是数组下标,count应该比i多1.
    return count;
}

27. 移除元素

##题目详情
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

题解

int removeElement(int* nums, int numsSize, int val) {
    int count=0; // 记录val值的个数
    for(int i=0;i<numsSize;i++){
        if(nums[i]==val) // 数组的值等于val值,count++
            count++;
        else
             nums[i-count]=nums[i];
    }
    return numsSize-count;
}

35. 搜索插入位置

题目详情

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

题解

int searchInsert(int* nums, int numsSize, int target) {
    int low=0,high=numsSize-1;
    while(low<=high){
        int mid=(low+high)/2;
        if(nums[mid]==target)
            return mid;
        else if(nums[mid]>target)
            high=mid-1;
        else
            low=mid+1;
    }
    return low; // low指向的位置是target元素应该在数组中存放的位置
}

66. 加1

题目详情

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

题解

int* plusOne(int* digits, int digitsSize, int* returnSize) {
   for(int i=digitsSize-1;i>=0;i--){
       if(digits[i]<9){
           digits[i]++;
           (*returnSize)=digitsSize;
           return digits;
       }else{
           digits[i]=0;
       }
   }
   int* res=(int*)malloc(sizeof(int)*(digitsSize+1));
   res[0]=1;
   for(int i=1;i<digitsSize+1;i++)
        res[i]=digits[i-1];
    (*returnSize)=digitsSize+1;
    return res;     
}

88. 合并两个有序数组

题目详情

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

题解

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int i, j = 0, k = 0, tempNums1[nums1Size];
    for (i = 0; i < m; i++) // 移动元素到tempNums1中
        tempNums1[i] = nums1[i];
    i = 0;
    while (i < m && j < n) {
        if (tempNums1[i] < nums2[j]) {
            nums1[k++]=tempNums1[i++];
        }else{
            nums1[k++]=nums2[j++];
        }
    }
    while(i<m){
        nums1[k++]=tempNums1[i++];
    }
    while(j<n){
        nums1[k++]=nums2[j++];
    }
}

108. 将有序数组转换为二叉搜索树

题目详情

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

题解

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* travel(int nums[],int low,int high){
    if(low>high) return NULL;
    int mid=(low+high)/2;
    struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=nums[mid];
    root->left=travel(nums,low,mid-1);
    root->right=travel(nums,mid+1,high);
    return root;
}
 
struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
    struct TreeNode* head=travel(nums,0,numsSize-1);
    return head;
}

注意

// 第一种
struct TreeNode{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
}TLnode;

// 第二种
struct TreeNode{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
};

// 为第一种的话,函数的返回值可以写为 TLnode 或 struct TreeNode
// 为第一种的话,函数的返回值可以写为 struct TreeNode

118. 杨辉三角

题目详情

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

题解

int** generate(int numRows, int* returnSize, int** returnColumnSizes){
    //返回的是二维数组,所以需要保存每一行的信息
    *returnSize = numRows;  // 返回有几列
    *returnColumnSizes = (int *)malloc(sizeof(int)*numRows);//returnColumnSizes储存杨辉三角每一行元素的个数
    int** res = (int**)malloc(sizeof(int*)*numRows);
    
    for (int i = 0; i < numRows; i++) {
        (*returnColumnSizes)[i] = i+1;
        res[i] = (int*)malloc(sizeof(int)*(i+1));
        res[i][0] = 1;
        res[i][i] = 1;
        for (int j = 1; j < i; j++) {
            res[i][j] = res[i-1][j] + res[i-1][j-1]; 
        }
    }
    return res;
}

119. 杨辉三角 II

题目详情

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。
示例 1:

输入: rowIndex = 3
输出: [1,3,3,1]
示例 2:

输入: rowIndex = 0
输出: [1]
示例 3:

输入: rowIndex = 1
输出: [1,1]

题解

int* getRow(int rowIndex, int* returnSize) {
    *returnSize = (rowIndex + 1);
    int** arr = (int**)malloc(sizeof(int*) * (rowIndex+1));
    int i, j;
    for (i = 0; i < rowIndex+1; i++) {
        arr[i] = (int*)malloc(sizeof(int) * (i + 1));
        arr[i][0] = 1;
        arr[i][i] = 1;
        for (j = 1; j < i; j++) {
            arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
        }
    }
    return arr[rowIndex];
}

136. 只出现一次的数字

题目详情

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1 :

输入:nums = [2,2,1]
输出:1
示例 2 :

输入:nums = [4,1,2,1,2]
输出:4
示例 3 :

输入:nums = [1]
输出:1

题解

int singleNumber(int* nums, int numsSize) {
    int res=0;
    for(int i=0;i<numsSize;i++)
        res^=nums[i];
    return res;
}

169. 多数元素

题目详情

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入:nums = [3,2,3]
输出:3
示例 2:

输入:nums = [2,2,1,1,1,2,2]
输出:2

题解

int majorityElement(int* nums, int numsSize) {
    int i, vote = 0,
           elector; // vote 投票数 elector 选举者(把数组里面的数字看做选举者)
    for (i = 0; i < numsSize; i++) {
        if (!vote) {
            elector = nums[i];
        }
        if (elector == nums[i])
            vote++;
        else
            vote--;
    }
    return elector;
}

摩尔投票算法

该算法的核心就是对拼消耗

摩尔投票算法的优点

时间复杂度低:算法只需要遍历数组两次,时间复杂度为O(n),其中n是数组长度。
空间复杂度低:算法只需要常数级的额外空间,因此空间复杂度为O(1)。 ●
高效:适用于大规模数据,能够在较短时间内找到主要元素。

摩尔投票算法的缺点

  1. 不适用于所有情况:==算法要求主要元素的出现次数超过一半,因此对于没有主要元素的情况不适用。 ==
  2. 需要额外验证:算法找到候选主要元素后,还需要额外的遍历来验证其是否真的满足条件。
    摩尔投票算法

你可能感兴趣的:(算法笔记,算法,数据结构,leetcode)