数据结构算法题——数组

leetcode-1.两数之和

leetcode-1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int *result = NULL;
    for(int i = 0; i < numsSize - 1; i++){
        for(int j = i + 1; j < numsSize; j++){
            if(nums[i] + nums[j] == target){
                result = (int*)malloc(sizeof(int)*2);
                result[0] = i;
                result[1] = j;
                *returnSize = 2;
                return result;
            }
        }
    }
    return result;
}

leetcode-4.寻找两个正序数组的中位数

leetcode-4.寻找两个正序数组的中位数(二分版)
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数

算法的时间复杂度应该为 O(log (m+n)) 。

#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
    if(nums1Size > nums2Size){
        return findMedianSortedArrays(nums2, nums2Size, nums1, nums1Size);  // 保证numsSize1 < nums2Size
    }
    int iMin = 0, iMax = nums1Size;
    int i, j;
    while(iMin <= iMax){
        i = (iMin + iMax) / 2;
        j = (nums1Size + nums2Size + 1) / 2 - i;
        if(i != nums1Size && j != 0 && nums1[i] < nums2[j-1]){  // i 需要增大
            iMin = i + 1;
        }
        else if(i != 0 && j != nums2Size && nums1[i-1] > nums2[j]){     // i 需要减小
            iMax = i - 1;
        }
        else{
            break;
        }
    }
    int maxLeft = 0;
    if(i == 0){
        maxLeft = nums2[j-1];
    }
    else if(j == 0){
        maxLeft = nums1[i-1];
    }
    else{
        maxLeft = max(nums1[i-1], nums2[j-1]);
    }
    if((nums1Size + nums2Size) % 2 == 1){   // 奇数的话中位数在左半部分最右,不需要考虑右半部分
        return maxLeft;
    }
    int minRight = 0;
    if(i == nums1Size){
        minRight = nums2[j];
    }
    else if(j == nums2Size){
        minRight = nums1[i];
    }
    else{
        minRight = min(nums1[i], nums2[j]);
    }
    return (maxLeft + minRight) / 2.0;  //偶数结果为左边最大值与右边最小值的平均
}

时间复杂度:我们对较短的数组进行了二分查找,所以时间复杂度是O(log(min(m, n))
空间复杂度:只有一些固定的变量,和数组长度无关,所以空间复杂度是O(1)

leetcode-11.盛最多水的容器

leetcode-11.盛最多水的容器
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

#define min(a,b) (((a) < (b)) ? (a) : (b))

int maxArea(int* height, int heightSize){
    int i = 0, j = heightSize - 1;
    int mx = 0, high, width;
    while(i < j){
        high = min(height[i], height[j]);
        width = j - i;
        if(mx < high * width){
            mx = high * width;
        }
        if(height[i] < height[j]){
            i++;
        }
        else{
            j--;
        }
    }
    return mx;
}

时间复杂度:只需要双指针遍历一遍底边宽度,所以为O(n)
空间复杂度:变量i,j,mx等,使用常数额外空间,所以为O(1)

这题有个问题,如果存在相等的情况,如8,1,2,3,4,5,6,7,8,答案好像就不对了。

leetcode-15.三数之和(快速排序+双指针)

leetcode-15.三数之和(快速排序+双指针)
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

void quickSort(int* nums, int first, int end)   // 快速排序
{
    int temp, l, r;
    if(first >= end)
        return;
    temp = nums[first];
    l = first, r = end;
    while(l < r){
        while(l < r && temp <= nums[r])
            r--;
        if(l < r)
            nums[l] = nums[r];
        while(l < r && nums[l] <= temp)
            l++;
        if(l < r)
            nums[r] = nums[l];
    }
    nums[l] = temp;
    quickSort(nums, first, l - 1);
    quickSort(nums, l + 1, end);
}

int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    if(numsSize < 3)
        return NULL;
    quickSort(nums, 0, numsSize - 1);
    int** f = (int**)malloc(sizeof(int*) * numsSize * numsSize);
    *returnColumnSizes = (int**)malloc(sizeof(int*) * numsSize * numsSize);
    *returnSize = 0;
    for(int i = 0; i < numsSize - 2; i++){
        if(nums[i] > 0)
            break;
        if(i != 0 && nums[i] == nums[i-1])
            continue;
        int left = i + 1, right = numsSize - 1;
        while(left < right){
            int sum = nums[i] + nums[right] + nums[left];
            if(sum == 0){
                f[*returnSize] = (int*)malloc(sizeof(int) * 3);
                f[*returnSize][0] = nums[i];
                f[*returnSize][1] = nums[right];
                f[*returnSize][2] = nums[left];
                (*returnColumnSizes)[*returnSize] = 3;
                *returnSize = *returnSize + 1;
                int a, b;
                do{
                    a = left;
                    left = left + 1;
                }while(a < right && nums[a] == nums[left]);
                do{
                    b = right;
                    right = right - 1;
                }while(b > left && nums[b] == nums[right]);
            }
           else if(sum < 0){
               left++;
           }
           else{
               right--;
           }
        }
    }
    return f;
}

时间复杂度:O(n2),其中 n 是数组 nums 的长度。
空间复杂度:O(logn)。我们忽略存储答案的空间,额外的排序的空间复杂度为 O(logn)。然而我们修改了输入的数组 nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了 nums 的副本并进行排序,空间复杂度为 O(n)。

leetcode-16.最接近的三数之和(快速排序+双指针)

leetcode-16.最接近的三数之和(快速排序+双指针)
给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

void quickSort(int* nums, int first, int end)   // 快速排序
{
    if(first >= end)
        return;
    int temp = nums[first];
    int l = first, r = end;
    while(l < r){
        while(l < r && temp <= nums[r])
            r--;
        if(l < r)
            nums[l] = nums[r];
        while(l < r && nums[l] <= temp)
            l++;
        if(l < r)
            nums[r] = nums[l];
    }
    nums[l] = temp;
    quickSort(nums, first, l - 1);
    quickSort(nums, l + 1, end);
}

int threeSumClosest(int* nums, int numsSize, int target){
    if(numsSize < 3)
        return 0;
    quickSort(nums, 0, numsSize - 1);
    int mn = INT_MAX, ans;
    for(int i = 0; i < numsSize - 2; i++){
        int left = i + 1, right = numsSize - 1;
        while(left < right){
            int sum = nums[i] + nums[left] + nums[right];
            if(sum == target)
                return sum;
            if(mn > abs(sum - target)){
                mn = abs(sum - target);
                ans = sum;
            }
            if(sum > target){
                int m;
                do{
                    m = right;
                    right = right - 1;
                }while(m > left && nums[m] == nums[right]);
            }
            else{
                int n;
                do{
                    n = left;
                    left = left + 1;
                }while(n < right && nums[n] == nums[left]);
            }
        }
    }
    return ans;
}

时间复杂度:O(n2),其中 n 是数组 nums 的长度。
空间复杂度:O(logn)。排序需要使用 O(logn) 的空间。然而我们修改了输入的数组 nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了 nums 的副本并进行排序,此时空间复杂度为 O(n)。

leetcode-18.四数之和(快速排序+双指针)

leetcode-18.四数之和(快速排序+双指针)
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

void quickSort(int* nums, int start, int end)
{
    if(start >= end)
        return;
    int temp = nums[start];
    int l = start, r = end;
    while(l < r){
        while(l < r && temp <= nums[r])
            r--;
        if(l < r)
            nums[l] = nums[r];
        while(l < r && nums[l] <= temp)
            l++;
        if(l < r)
            nums[r] = nums[l];
    }
    nums[l] = temp;
    quickSort(nums, start, l - 1);
    quickSort(nums, l + 1, end);
}

int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
    quickSort(nums, 0, numsSize - 1);
    int** f = (int**)malloc(sizeof(int*) * 1001);
    *returnColumnSizes = (int*)malloc(sizeof(int) * 1001);
    *returnSize = 0;
    if(numsSize < 4 || nums == NULL)
        return NULL;
    for(int i = 0; i < numsSize - 3; i++){
        if(i > 0 && nums[i] == nums[i-1])
            continue;
        if((long)nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target)
            break;
        if((long)nums[i] + nums[numsSize-3] + nums[numsSize-2] + nums[numsSize-1] < target)
            continue;
        for(int j = i + 1; j < numsSize - 2; j++){
            if(j > i + 1 && nums[j] == nums[j-1])
                continue;
            if((long)nums[i] + nums[j] + nums[j+1] + nums[j+2] > target)
                break;
            if((long)nums[i] + nums[j] + nums[numsSize-2] + nums[numsSize-1] < target)
                continue;
            int left = j + 1, right = numsSize - 1;
            while(left < right){
                long sum = (long)nums[i] + nums[j] + nums[left] + nums[right];
                if(sum == target){
                    f[*returnSize] = (int*)malloc(sizeof(int) * 4);
                    f[*returnSize][0] = nums[i];
                    f[*returnSize][1] = nums[j];
                    f[*returnSize][2] = nums[left];
                    f[*returnSize][3] = nums[right];
                    (*returnColumnSizes)[*returnSize] = 4;
                    *returnSize = *returnSize + 1;
                    int a, b;
                    do{
                        a = left;
                        left = left + 1;
                    }while(a < right && nums[a] == nums[left]);
                    do{
                        b = right;
                        right = right - 1;
                    }while(b > left && nums[b] == nums[right]);
                }
                else if(sum > target){
                    right = right - 1;
                }
                else{
                    left = left + 1;
                }
            }
        }
    }
    return f;
}

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

leetcode-26.删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

int removeDuplicates(int* nums, int numsSize){
    int pre = nums[0], l = 1;
    for(int i = 1; i < numsSize; i++){
        if(nums[i] != pre){
            nums[l] = nums[i];
            pre = nums[l];
            l = l + 1;
        }
    }
    return l;
}

时间复杂度:O(n),其中 n 是数组的长度。
空间复杂度:O(1)。只需要使用常数的额外空间。

leetcode-27.移除元素

leetcode-27.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

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

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

int removeElement(int* nums, int numsSize, int val){
    int left = 0, right = numsSize;
    while(left < right){
        if(nums[left] == val){
            nums[left] = nums[right-1];
            right--;
        }
        else{
            left++;
        }
    }
    return left;
}

时间复杂度:O(n),其中 n 为序列的长度。我们只需要遍历该序列至多一次。
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。

leetcode-33.搜索旋转排序数组(二分查找)

leetcode-33.搜索旋转排序数组(二分查找)
整数数组 nums 按升序排列,数组中的值 互不相同

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

int search(int* nums, int numsSize, int target){
    int i = 0, j = numsSize - 1;
    while(i <= j){
        int mid = (i + j) / 2;
        if(nums[mid] == target){
            return mid;
        } 
        if(nums[mid] < nums[j]){    // 当(mid,j]区间有序时
            if(nums[mid] < target && target <= nums[j]){
                i = mid + 1;
            }
            else{
                j = mid - 1;
            }
        }
        else{   // 当[i,mid)区间有序时
            if(nums[i] <= target && target <nums[mid]){
                j = mid - 1;
            }
            else{
                i = mid + 1;
            }
        }
    }
    return -1;
}

时间复杂度:O(logn),其中 n为 nums 数组的大小。整个算法时间复杂度即为二分查找的时间复杂度 O(logn)。
空间复杂度:O(1) 。我们只需要常数级别的空间存放变量。

leetcode-34.在排序数组中查找元素的第一个和最后一个位置(二分查找)

leetcode-34.在排序数组中查找元素的第一个和最后一个位置(二分查找)
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]。

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

int binarySearch(int* nums, int numsSize, int target, bool lower)
{
    int left = 0, right = numsSize - 1, ans = numsSize;
    while(left <= right){
        int mid = (left + right) / 2;
        if(nums[mid] > target || (lower && nums[mid] >= target)){
            right = mid - 1;
            ans = mid;
        }
        else{
            left = mid + 1;
        }
    }
    return ans;
}

int* searchRange(int* nums, int numsSize, int target, int* returnSize){
    int lindex = binarySearch(nums, numsSize, target, true);
    int rindex = binarySearch(nums, numsSize, target, false) - 1;
    int* ret = malloc(sizeof(int) * 2);
    *returnSize = 2;
    if(lindex <= rindex && rindex < numsSize && nums[lindex] == target && nums[rindex] == target){
        ret[0] = lindex;
        ret[1] = rindex;
    }
    else{
        ret[0] = -1;
        ret[1] = -1;
    }
    return ret;
}

时间复杂度:O(logn),其中 n 为数组的长度。二分查找的时间复杂度为 O(logn),一共会执行两次,因此总时间复杂度为 O(logn)。
空间复杂度:O(1) 。只需要常数空间存放若干变量。

leetcode-35.搜索插入位置(二分查找)

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

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

int searchInsert(int* nums, int numsSize, int target){
    int i = 0, j = numsSize - 1;
    while(i <= j){
        int mid = (i + j) / 2;
        if(nums[mid] < target){
            i = mid + 1;
        }
        else{
            j = mid - 1;
        }
    }
    return i;
}

时间复杂度:O(logn),其中 n 为数组的长度。二分查找所需的时间复杂度为 O(logn)。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。

leetcode-41.缺失的第一个正数

leetcode-41.缺失的第一个正数
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

方法一:哈希表

int firstMissingPositive(int* nums, int numsSize){
    for(int i = 0; i < numsSize; i++){
        if(nums[i] <= 0){
            nums[i] = numsSize + 1;
        }
    }
    for(int i = 0; i < numsSize; i++){
        int num = abs(nums[i]);
        if(num <= numsSize){
            nums[num - 1] = -abs(nums[num - 1]);
        }
    }
    for(int i = 0; i <  numsSize; i++){
        if(nums[i] > 0){
            return i + 1;
        }
    }
    return numsSize + 1;
}

时间复杂度:O(N),其中 N 是数组的长度。
空间复杂度:O(1)。

方法二:置换

int firstMissingPositive(int* nums, int numsSize){
    for(int i = 0; i < numsSize; i++){
        while(nums[i] > 0 && nums[i] <= numsSize && nums[nums[i] - 1] != nums[i] ){
            int t = nums[nums[i] - 1];
            nums[nums[i] - 1] = nums[i];
            nums[i] = t;
        }
    }
    for(int i = 0; i < numsSize; i++){
        if(nums[i] != i + 1){
            return i + 1;
        }
    }
    return numsSize + 1;
}

时间复杂度:O(N),其中 N 是数组的长度。
空间复杂度:O(1)。

leetcode-42.接雨水

leetcode-42.接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述

#define max(a,b) (a > b) ? a : b

int trap(int* height, int heightSize){
    int ans = 0, left = 0, right = heightSize - 1;
    int maxLeft = height[left], maxRight = height[right];
    while(left < right){
        maxLeft = max(maxLeft, height[left]);
        maxRight = max(maxRight, height[right]);
        if(maxLeft < maxRight){
            ans += maxLeft - height[left];
            left++;
        }
        else{
            ans += maxRight - height[right];
            right--;
        }
    }
    return ans;
}

时间复杂度:O(n),其中 n 是数组height 的长度。两个指针的移动总次数不超过 n。
空间复杂度:O(1)。只需要使用常数的额外空间。

leetcode-45.跳跃游戏 II

leetcode-45.跳跃游戏 II
给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

int jump(int* nums, int numsSize){
    int end = 0;    // 边界
    int maxPosition = 0;    // 所能跳到的最大位置
    int step = 0;   // 记录跳跃数
    for(int i = 0; i < numsSize - 1; i++){
        maxPosition = maxPosition > nums[i] + i ? maxPosition : nums[i] + i;    // 找能跳到的最远的
        if(i == end){   // 遇到边界,就更新边界,并且步数加一
            end = maxPosition;
            step++;
        }
    }
    return step;
}

时间复杂度:O(n),其中 n 是数组长度。
空间复杂度:O(1)。

leetcode-46.全排列

leetcode-46.全排列
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

int vis[1024] = {0};

void dfs(int* nums, int numsSize, int n, int arr[], int** res, int* ind, int** returnColumnSizes)
{
    if(n == numsSize){
        res[*ind] = (int*)malloc(sizeof(int) * (numsSize + 5));
        for(int i = 0; i < numsSize; i++){
            res[*ind][i] = arr[i];
        }
        (*returnColumnSizes)[*ind] = numsSize;
        (*ind)++;
        return ;
    }
    for(int i = 0; i < numsSize; i++){
        if(vis[i] == 1) continue;
        vis[i] = 1;
        arr[n] = nums[i];
        dfs(nums, numsSize, n + 1, arr, res, ind, returnColumnSizes);
        vis[i] = 0;
    }
}

int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    *returnSize = 0;
    if(numsSize == 0)
        return 0;
    int cnt = 1, k = 1;
    while(k <= numsSize){
        cnt = cnt * k;
        k++;
    }
    int** res = (int**)malloc(sizeof(int**) * cnt);
    *returnColumnSizes = (int*)malloc(sizeof(int) * cnt);
    int arr[numsSize + 5], ind = 0;
    dfs(nums, numsSize, 0, arr, res, &ind, returnColumnSizes);
    *returnSize = ind;
    return res;
}

时间复杂度:O(n×n!),其中 n 为序列的长度。而对于dfs 调用的每个叶结点(共 n! 个),我们需要将当前答案使用 O(n) 的时间复制到答案数组中,相乘得时间复杂度为 O(n×n!)。因此时间复杂度为 O(n×n!)。
空间复杂度:O(n),其中 n 为序列的长度。除答案数组以外,递归函数在递归过程中需要为每一层递归函数分配栈空间,所以这里需要额外的空间且该空间取决于递归的深度,这里可知递归调用深度为 O(n)。

leetcode-47.全排列 II

leetcode-47.全排列 II
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

int vis[1024] = {0};

void quickSort(int* nums, int start, int end)
{
    if(start >= end)
        return ;
    int temp = nums[start];
    int l = start, r = end;
    while(l < r){
        while(l < r && temp <= nums[r])
            r--;
        if(l < r)
            nums[l] = nums[r];
        while(l < r && nums[l] <= temp)
            l++;
        if(l < r)
            nums[r] = nums[l];
    }
    nums[l] = temp;
    quickSort(nums, start, l - 1);
    quickSort(nums, l + 1, end);
}

void dfs(int* nums, int numsSize, int n, int** res, int arr[], int* ind, int** returnColumnSizes)
{
    if(n == numsSize){
        res[*ind] = (int*)malloc(sizeof(int) * (numsSize + 5));
        for(int i = 0; i < numsSize; i++){
            res[*ind][i] = arr[i];
        }
        (*returnColumnSizes)[*ind] = numsSize;
        (*ind)++;
    }
    for(int i = 0; i < numsSize; i++){
        if(vis[i] == 1) continue;
        vis[i] = 1;
        arr[n] = nums[i];
        dfs(nums, numsSize, n + 1, res, arr, ind, returnColumnSizes);
        vis[i] = 0;
        while(i < numsSize - 1 && nums[i] == nums[i+1]) i++;
    }
}

int** permuteUnique(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    *returnSize = 0;
    if(numsSize == 0)
        return 0;
    int cnt = 1, k = 1;
    while(k <= numsSize){
        cnt = cnt * k;
        k++;
    }
    int** res = (int**)malloc(sizeof(int*) * cnt);
    *returnColumnSizes = (int*)malloc(sizeof(int) * cnt);
    int arr[numsSize + 5], ind = 0;
    quickSort(nums, 0, numsSize - 1);
    dfs(nums, numsSize, 0, res, arr, &ind, returnColumnSizes);
    *returnSize = ind;
    return res;
}

时间复杂度:O(n×n!),其中 n 为序列的长度。
空间复杂度:O(n)。我们需要 O(n) 的标记数组,同时在递归的时候栈深度会达到 O(n),因此总空间复杂度为 O(n + n) = O(2n) = O(n)。

leetcode-53.最大子数组和

leetcode-53.最大子数组和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

int maxSubArray(int* nums, int numsSize)
{
    int pre = 0, maxAns = nums[0];
    for(int i = 0; i < numsSize; i++){
        pre = fmax(pre + nums[i], nums[i]);
        maxAns = fmax(maxAns, pre);
    }
    return maxAns;
}

时间复杂度:O(n),其中 n 为 nums 数组的长度。我们只需要遍历一遍数组即可求得答案。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。

leetcode-55.跳跃游戏

leetcode-55.跳跃游戏
给定一个非负整数数组 nums ,你最初位于数组的 第一个下标

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

bool canJump(int* nums, int numsSize){
    int end = 0;
    int maxPosition = 0;
    for(int i = 0; i < numsSize; i++){
        maxPosition = maxPosition > nums[i] + i ? maxPosition : nums[i] + i;
        if(i == end){
            end = maxPosition;
        }
    }
    if(end >= numsSize - 1)
        return true;
    else
        return false;
}

时间复杂度:O(n),其中 n 为数组的大小。只需要访问 nums 数组一遍,共 n 个位置。
空间复杂度:O(1),不需要额外的空间开销。

leetcode-66.加一

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

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

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

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

时间复杂度:O(n),其中 n 是数组 digits 的长度。
空间复杂度:O(n)。

leetcode-75.颜色分类

leetcode-75.颜色分类
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

必须在不使用库的sort函数的情况下解决这个问题。

void swap(int* a, int* b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

void sortColors(int* nums, int numsSize)
{
    int l = 0, r = numsSize - 1;
    for(int i = 0; i < numsSize; i++){
        while(i <= r && nums[i] == 2){
            swap(&nums[i], &nums[r]);
            r--;
        }
        if(nums[i] == 0){
            swap(&nums[l], &nums[i]);
            l++;
        }
    }
}

时间复杂度:O(n),其中 n 是数组nums 的长度。
空间复杂度:O(1)。

leetcode-77.组合

leetcode-77.组合
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

int vis[100] = {0};

void dfs(int n, int k, int* ind, int** returnColumnSizes, int** ans, int arr[], int t, int s)
{
    if(k == t){
        ans[*ind] = (int*)malloc(sizeof(int) * (k + 5));
        for(int i = 0; i < k; i++){
            ans[*ind][i] = arr[i];
        }
        (*returnColumnSizes)[*ind] = k;
        (*ind)++;
    }
    for(int i = s; i <= n; i++){
        vis[i] = 1;
        arr[t] = i;
        dfs(n, k, ind, returnColumnSizes, ans, arr, t + 1, i + 1);
        vis[i] = 0;
    }
}

int** combine(int n, int k, int* returnSize, int** returnColumnSizes){
    if(k == 0)
        return 0;
    int ind = 0, arr[5000];
    int** ans = (int**)malloc(sizeof(int*) * 5000);
    *returnColumnSizes = (int*)malloc(sizeof(int) * 5000);
    dfs(n, k, &ind, returnColumnSizes, ans, arr, 0, 1);
    *returnSize = ind;
    return ans;
}

leetcode-78.子集

leetcode-78.子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

int** ans;
int* ansColSize;
int ansSize;
int* t;
int tSize;

void dfs(int cur, int* nums, int numsSize)
{
    if(cur == numsSize){
        int* tmp = malloc(sizeof(int) * tSize);
        memcpy(tmp, t, sizeof(int) * tSize);
        ansColSize[ansSize] = tSize;
        ans[ansSize++] = tmp;
        return ;
    }
    t[tSize++] = nums[cur];
    dfs(cur + 1, nums, numsSize);
    tSize--;
    dfs(cur + 1, nums, numsSize);
}

int** subsets(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    ans = malloc(sizeof(int*) * (1 << numsSize));
    ansColSize = malloc(sizeof(int) * (1 << numsSize));
    t = malloc(sizeof(int) * numsSize);
    *returnSize = 1 << numsSize;
    ansSize = tSize = 0;
    dfs(0, nums, numsSize);
    *returnColumnSizes = ansColSize;
    return ans;
}

时间复杂度:O(n × 2n)。一共2n个状态,每种状态需要 O(n) 的时间来构造子集。
空间复杂度:O(n)。临时数组 t 的空间代价是 O(n),递归时栈空间的代价为 O(n)。

leetcode-80.删除有序数组中的重复项 II

leetcode-80.删除有序数组中的重复项 II
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

int removeDuplicates(int* nums, int numsSize){
    int t = 1, pre = nums[0], idx = 0;
    for(int i = 1; i < numsSize; i++){
        if(nums[i] == pre){
            t++;
            if(t <= 2){
                idx = idx + 1;
                nums[idx] = nums[i];
            }

        }
        else{
            pre = nums[i];
            t = 1;
            idx = idx + 1;
            nums[idx] = nums[i];
        }
    }
    return idx + 1;
}

时间复杂度:O(n)。
空间复杂度:O(1)。

leetcode-81.搜索旋转排序数组 II

leetcode-81.搜索旋转排序数组 II
已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。

给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 true ,否则返回 false 。

你必须尽可能减少整个操作步骤。

bool search(int* nums, int numsSize, int target){
    int left = 0, right = numsSize - 1;
    while(left <= right){
        int mid = (left + right) / 2;
        if(nums[mid] == target){
            return true;
        }
        if(nums[left] == nums[mid] && nums[mid] == nums[right]){
            left++;
            right--;
        }
        else if(nums[mid] <= nums[right]){
            if(nums[mid] < target && target <= nums[right]){
                left = mid + 1;
            }
            else{
                right = mid - 1;
            }
        }
        else{
            if(nums[left] <= target && target < nums[mid]){
                right = mid - 1;
            }
            else{
                left = mid + 1;
            }
        }
    }
    return false;
}

时间复杂度:O(n),其中 n 是数组 nums 的长度。最坏情况下数组元素均相等且不为 target,我们需要访问所有位置才能得出结果。
空间复杂度:O(1)。

leetcode-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 t1 = m - 1, t2 = n - 1;
    int tail = m + n - 1;
    while(t1 >= 0 || t2 >= 0){
        if(t1 == -1){
            nums1[tail--] = nums2[t2--];
        }
        else if(t2 == -1){
            nums1[tail--] = nums1[t1--];
        }
        else if(nums1[t1] < nums2[t2]){
            nums1[tail--] = nums2[t2--];
        }
        else{
            nums1[tail--] = nums1[t1--];
        }
    }
}

时间复杂度:O(m + n)。指针移动单调递减,最多移动 m+n 次,因此时间复杂度为 O(m+n)。
空间复杂度:O(1)。直接对数组 nums1 原地修改,不需要额外空间。

leetcode-152.乘积最大子数组

leetcode-152.乘积最大子数组
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

测试用例的答案是一个 32-位 整数。

子数组 是数组的连续子序列。

int maxProduct(int* nums, int numsSize){
    int minF = nums[0], maxF = nums[0], ans = nums[0];
    for(int i = 1; i < numsSize; i++){
        int mn = minF, mx = maxF;
        maxF = fmax(nums[i] * mx, fmax(nums[i], nums[i] * mn));
        minF = fmin(nums[i] * mn, fmin(nums[i], nums[i] * mx));    
        ans = fmax(maxF, ans);
    }
    return ans;
}

时间复杂度:程序一次循环遍历了 nums,故渐进时间复杂度为 O(n)。
空间复杂度:优化后只使用常数个临时变量作为辅助空间,与 n 无关,故渐进空间复杂度为 O(1)。

leetcode-153.寻找旋转排序数组中的最小值

leetcode-153.寻找旋转排序数组中的最小值
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

int findMin(int* nums, int numsSize){
    int left = 0, right = numsSize - 1;
    while(left < right){
        int mid = left + (right - left) / 2;
        if(nums[mid] < nums[right]){
            right = mid;
        }
        else{
            left = mid + 1;
        }
    }
    return nums[left];
}

时间复杂度:时间复杂度为 O(logn),其中 n 是数组 nums 的长度。在二分查找的过程中,每一步会忽略一半的区间,因此时间复杂度为 O(logn)。
空间复杂度:O(1)。

leetcode-154. 寻找旋转排序数组中的最小值 II

leetcode-154. 寻找旋转排序数组中的最小值 II
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
  • 若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]

注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

你必须尽可能减少整个过程的操作步骤。

int findMin(int* nums, int numsSize){
    int left = 0, right = numsSize - 1;
    while(left < right){
        int mid = left + (right - left) / 2;
        if(nums[mid] < nums[right]){
            right = mid;
        }
        else if(nums[mid] > nums[right]){
            left = mid + 1;
        }
        else{
            right--;
        }
    }
    return nums[left];
}

时间复杂度:平均时间复杂度为 O(logn),其中 n 是数组 nums 的长度。如果数组是随机生成的,那么数组中包含相同元素的概率很低,在二分查找的过程中,大部分情况都会忽略一半的区间。而在最坏情况下,如果数组中的元素完全相同,那么 while 循环就需要执行 n 次,每次忽略区间的右端点,时间复杂度为 O(n)。
空间复杂度:O(1)。

leetcode-162.寻找峰值

leetcode-162.寻找峰值
峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = − ∞ -\infty

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

int findPeakElement(int* nums, int numsSize){
    int left = 0, right = numsSize - 1;
    while(left < right){
        int mid = left + ((right - left) >> 1);
        if(nums[mid] < nums[mid + 1]){
            left = mid + 1;
        }
        else{
            right = mid;
        }
    }
    return left;
}

时间复杂度:O(logn),其中 n 是数组 nums 的长度。
空间复杂度:O(1)。

leetcode-169.多数元素

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

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

int majorityElement(int* nums, int numsSize){
    int num = nums[0], cnt = 1;
    for(int i = 1; i < numsSize; i++){
        if(num == nums[i]){
            cnt++;
        }
        else if(cnt == 1){
            num = nums[i];
        }
        else{
            cnt--;
        }
    }
    cnt = 0;
    for(int i = 0; i < numsSize; i++){
        if(num == nums[i]){
            cnt++;
        }
    }
    return cnt > numsSize / 2 ? num : -1;
}

时间复杂度:O(n)。
空间复杂度:O(1)。

leetcode-189.轮转数组

leetcode-189.轮转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

void swap(int* a, int* b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

void reverse(int* nums, int start, int end)
{
    while(start < end){
        swap(&nums[start], &nums[end]);
        start++;
        end--;
    }
}

void rotate(int* nums, int numsSize, int k){
    k = k % numsSize;
    reverse(nums, 0, numsSize - 1);
    reverse(nums, 0, k - 1);
    reverse(nums, k, numsSize - 1);
}

时间复杂度:O(n),其中 n 为数组的长度。每个元素被翻转两次,一共 n 个元素,因此总时间复杂度为 O(2n)=O(n)。
空间复杂度:O(1)。

leetcode-209.长度最小的子数组

leetcode-209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

int minSubArrayLen(int target, int* nums, int numsSize){
    if(numsSize == 0){
        return 0;
    }
    int ans = INT_MAX;
    int start = 0, end = 0;
    int sum = 0;
    while(end < numsSize){
        sum += nums[end];
        while(sum >= target){
            ans = fmin(ans, end - start + 1);
            sum -= nums[start];
            start++;
        }
        end++;
    }
    return ans == INT_MAX ? 0 : ans;
}

时间复杂度:O(n),其中 n 是数组的长度。指针 start 和 end 最多各移动 n 次。
空间复杂度:O(1)。

leetcode-217.存在重复元素

leetcode-217.存在重复元素
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

int cmp(const void* _a, const void* _b) {
    int a = *(int*)_a, b = *(int*)_b;
    return a - b;
}

bool containsDuplicate(int* nums, int numsSize){
    qsort(nums, numsSize, sizeof(int), cmp);
    // quicksort(nums, 0, numsSize - 1);	// 不知道为什么自己写的快排会超时
    for(int i = 0; i < numsSize - 1; i++){
        if(nums[i] == nums[i+1]){
            return true;
        }
    }
    return false;
}

时间复杂度:O(NlogN),其中 N 为数组的长度。需要对数组进行排序。
空间复杂度:O(logN),其中 N 为数组的长度。注意我们在这里应当考虑递归调用栈的深度。

leetcode-238.除自身以外数组的乘积

leetcode-238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

不要使用除法,且在 O(n) 时间复杂度内完成此题。

int* productExceptSelf(int* nums, int numsSize, int* returnSize){
    int* answer = (int*)malloc(sizeof(int) * numsSize);
    answer[0] = 1;
    for(int i = 1; i < numsSize; i++){
        answer[i] = answer[i - 1] * nums[i - 1];
    }
    int r = 1;
    for(int i = numsSize - 1; i >= 0; i--){
        answer[i] = answer[i] * r;
        r = r * nums[i];
    }
    *returnSize = numsSize;
    return answer;
}

时间复杂度:O(N),其中 N 指的是数组 nums 的大小。分析与方法一相同。
空间复杂度:O(1),输出数组不算进空间复杂度中,因此我们只需要常数的空间存放变量。

leetcode-274.H 指数

leetcode-274.H 指数
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数

根据维基百科上 h 指数的定义:h 代表“高引用次数”,一名科研人员的 h 指数 是指他(她)的 (n 篇论文中)总共 有 h 篇论文分别被引用了 至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。

如果 h 有多种可能的值,h 指数 是其中最大的那个。

int hIndex(int* citations, int citationsSize){
    int n = citationsSize, tot = 0;
    int cnt[n + 1];
    memset(cnt, 0, sizeof(cnt));
    for(int i = 0; i < n; i++){
        if(citations[i] > n){
            cnt[n]++;
        }
        else{
            cnt[citations[i]]++;
        }
    }
    for(int i = n; i >= 0; i--){
        tot += cnt[i];
        if(tot >= i){
            return i;
        }
    }
    return 0;
}

时间复杂度:O(n),其中 n 为数组 citations 的长度。需要遍历数组 citations 一次,以及遍历长度为 n+1 的数组 cnt 一次。
空间复杂度:O(n),其中 n 为数组 citations 的长度。需要创建长度为 n+1 的数组 cnt。

leetcode-275.H 指数 II(二分查找)

leetcode-275.H 指数 II(二分查找)
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数,citations 已经按照 升序排列 。计算并返回该研究者的 h 指数

h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。

提示:如果 h 有多种可能的值,h 指数 是其中最大的那个。

请你设计并实现对数时间复杂度的算法解决此问题。

int hIndex(int* citations, int citationsSize){
    int left = 0, right = citationsSize - 1;
    while(left <= right){
        int mid = left + (right - left) / 2;
        if(citations[mid] >= citationsSize - mid){
            right = mid - 1;
        }
        else{
            left = mid + 1;
        }
    }
    return citationsSize - left;
}

时间复杂度:O(log⁡n),其中 n 为数组 citations 的长度。二分查找的时间复杂度为 O(log⁡n)。
空间复杂度:O(1)。

leetcode-278.第一个错误的版本

leetcode-278.第一个错误版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

int firstBadVersion(int n) {
    int left = 1, right = n;
    while(left < right){
        int mid = left + (right - left) / 2;
        if(isBadVersion(mid)){
            right = mid;
        }
        else{
            left = mid + 1;
        }
    }
    return left;
}

时间复杂度:O(logn),其中 n 是给定版本的数量。
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。

leetcode-283.移动零

leetcode-283.移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

void swap(int *a, int *b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

void moveZeroes(int* nums, int numsSize){
    int left = 0, right = 0;
    while(right < numsSize){
        if(nums[right]){
            swap(nums + left, nums + right);
            left++;
        }
        right++;
    }
}

时间复杂度:O(n),其中 n 为序列长度。每个位置至多被遍历两次。
空间复杂度:O(1)。只需要常数的空间存放若干变量。

leetcode-334.递增子序列

leetcode-334.递增子序列
给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。

如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。

bool increasingTriplet(int* nums, int numsSize){
    if(numsSize < 3){
        return false;
    }
    int first = nums[0], second = INT_MAX;
    for(int i = 1; i < numsSize; i++){
        if(nums[i] > second){
            return true;
        }
        else if(nums[i] > first){
            second = nums[i];
        }
        else{
            first = nums[i];
        }
    }
    return false;
}

时间复杂度:O(n),其中 n 是 nums 数组的长度。需要遍历数组一次。
空间复杂度:O(1)。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值