26. 从排序数组中删除重复项
- 算法思想:
本算法类似于插入排序法,从元素0到元素number为已处理过的排序数组,从元素cur到数组末为未处理的数组,把每一个不重复的元素赋值到已处理过的排序数组,最后返回总长度为number+1。- 算法时间复杂度O(n)
int removeDuplicates(int* nums, int numsSize) {
if(numsSize == 0){
return 0;
}
int number = 0;
for(int cur = 0; cur < numsSize; cur++){
if(nums[cur] != nums[number]){
number++;
nums[number] = nums[cur];
}
}
return ++number;
}
122. 买卖股票的最佳时机 II
- 算法思想:
本算法将股票价格数组的处理变为每天与之前一天价格的差值,股价升高时判断有利润可交易,遍历一次数组。- 算法时间复杂度O(n)
int maxProfit(int* prices, int pricesSize) {
int profit = 0;
for(int i=0; i<pricesSize-1; i++){
int temp = prices[i+1]-prices[i];
if(temp>0)
profit += temp;
}
return profit;
}
189. 旋转数组
- 算法思想:
本算法将旋转分为三步的倒换- 算法时间复杂度O(n)
void rotate(int* nums, int numsSize, int k) {
k = k%numsSize;
if (k == 0)
return;
reverse(&nums[0], &nums[numsSize - k - 1]);
reverse(&nums[numsSize - k], &nums[numsSize - 1]);
reverse(&nums[0], &nums[numsSize - 1]);
}
void reverse(int*left, int*right){
while (left < right){
int temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}
217. 存在重复元素
- 算法思想:
本算法将数组进行排序,遍历一遍检查相邻元素是否相同- 算法时间复杂度O(nlogn)
int cmp(const void *a, const void *b){
return *(int*)a - *(int *)b;
}
bool containsDuplicate(int* nums, int numsSize){
if((NULL == nums) || (numsSize < 2))
return false;
qsort(nums, numsSize, sizeof(nums[0]), cmp);
for (int i = 0; i < numsSize-1; i++){
if (nums[i] == nums[i+1])
return true;
}
return false;
}
136. 只出现一次的数字
- 算法一思想:
本算法将数组进行排序,遍历一遍检查nums[2k]是否与下一个元素相等,单次出现的元素必定出现在不一致的nums[2k]上。- 算法时间复杂度O(nlogn)
- 算法二思想:
本算法来自Leetcode大佬们,通过将数组中所有元素与0进行异或,出现过两次的元素异或后仍未0,单次出现的元素异或后为原值;遍历一遍后可以得出单次出现的元素。- 算法时间复杂度O(n)
//算法一
int cmp(const void *a, const void *b){
return *(int*)a - *(int *)b;
}
int singleNumber(int* nums, int numsSize) {
int i;
qsort(nums, numsSize, sizeof(nums[0]), cmp);
for (i = 0; i < numsSize-1; i+=2){
if (nums[i] != nums[i+1])
return nums[i];
}
return nums[i];
}
//算法二
int singleNumber(int* nums, int numsSize) {
int result = 0;
for(int i=0; i<numsSize; i++)
result ^= nums[i];
return result;
}
350. 两个数组的交集 II
- 算法思想:
本算法将两个数组进行排序,一起遍历两个数组,当遇到相同的元素时复制到新的数组中。
Tips:注意这里的分配空间的函数- 算法时间复杂度O(nlogn)
int cmp(const void *a,const void *b)
{
return *(int *)a > *(int *)b ? 1 : -1;
}
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
if(nums1Size==0 || nums2Size==0)
return NULL;
int i=0,j=0;
int *newnums=(int*)malloc(sizeof(int)*nums1Size);
qsort(nums1, nums1Size, sizeof(nums1[0]), cmp);
qsort(nums2, nums2Size, sizeof(nums2[0]), cmp);
while(i<nums1Size&&j<nums2Size){
if(nums1[i]==nums2[j]){
newnums[(*returnSize)++]=nums1[i];
i++;
j++;
}
else if(nums1[i]<nums2[j])
i++;
else
j++;
}
if(*returnSize<nums1Size)
newnums=(int*)realloc(newnums,sizeof(int)*(*returnSize));
return newnums;
}
66. 加一
- 算法思想:
本算法将两个数组进行排序,一起遍历两个数组,当遇到相同的元素时复制到新的数组中。
Tips:注意这里的逻辑,当数字不全为9时,可以修改首位非9值,返回原地址,当数字为全9时,重新分配空间,位数加1。- 算法时间复杂度O(n)
int* plusOne(int* digits, int digitsSize, int* returnSize) {
int i = digitsSize - 1;
for(i;i >= 0;i--){
if(digits[i] < 9){
digits[i]++;
*returnSize = digitsSize;
return digits;
}
digits[i] = 0;
}
int* new = (int*) malloc ((digitsSize + 1) * sizeof (int));
new[0] = 1;
for(i = 1;i < (digitsSize + 1);i++)
new[i] = 0;
*returnSize = digitsSize + 1;
return new;
}
283. 移动零
- 算法思想:
本算法是采用双指针,一个指针指向所有原数组的元素,另一个指针指向所有非零元素存放的位置。- 算法时间复杂度O(n)
void moveZeroes(int* nums, int numsSize) {
int i = 0,j = 0;
for(i; i<numsSize;i++)
if (nums[i] != 0)
nums[j++] = nums[i];
for(j; j<numsSize; j++)
nums[j] = 0;
}
1. 两数之和
C语言解法转载自hang-7788的文章LeetCode 1.两数之和 Two Sum (C语言)
- 算法思想:
1.构造结构体,将数组的值与初始位置关联起来,并对结构体数组进行从小到大的排序。
2.使用下标begin和end,begin指向于开始的位置,end指向结束的位置,判断nums[begin] + nums[end]与target的关系。
- 如果相等,则直接返回索引;
- 如果比target大,则说明需要减小两数之和,即end–,来减小后者数字;
- 如果比target大,则说明需要增大两数之和,即begin++来增大前者数字。
- 3.通过这种方式逐渐逼近target,时间复杂度是O(nlogn)。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
struct node {
int val;
int index;
};
int comp(const void* a, const void* b) {
return (((struct node*)a)->val > ((struct node*)b)->val ? 1 : -1);
}
int* twoSum(int* nums, int numsSize, int target) {
int i = 0;
int n = numsSize;
int begin = 0, end = n - 1;
int* result = NULL;
struct node* nodes = (struct node*)malloc(n * sizeof(struct node));
// init nodes
for(i = 0; i < n; i++) {
nodes[i].val = nums[i];
nodes[i].index = i;
}
qsort(nodes, n, sizeof(struct node), comp);
while(begin < end) {
if(nodes[begin].val + nodes[end].val == target) {
result = (int*)malloc(sizeof(int) * 2);
result[0] = nodes[begin].index;
result[1] = nodes[end].index;
free(nodes);
return result;
}
else if(nodes[begin].val + nodes[end].val > target)
end--;
else
begin++;
}
free(nodes);
return result;
}
36. 有效的数独
- 算法思想:
维护三个分别代表行、列、块的三个数组,对于数独内每个单元值都在行、列、块中进行校验,遍历所有单元,如果全部通过即为有效- 时间复杂度是O(n)。
bool isValidPart(char **board, int i, int j, int *a)
{
char c = board[i][j];
if(c != '.')
{
int index = c - '1';
if(a[index]==1)return false;
else a[index]=1;
}
return true;
}
bool isValidSudoku(char** board, int boardRowSize, int boardColSize) {
int a[9]={0}; //标记一行
int b[9]={0}; //标记一列
int c[9][9]={0}; //c[i]标记一个9宫格
for(int i =0;i<9;i++)
{
memset(a,0,sizeof(int)*9);
memset(b,0,sizeof(int)*9);
for(int j=0;j<9;j++)
{
if(isValidPart(board, i, j, a)==false)return false;
if(isValidPart(board, j, i, b)==false)return false;
if(isValidPart(board, i, j, c[(i/3)*3 + j/3])==false)return false;
}
}
return true;
}
48. 旋转图像
- 算法一思想:
将图像先转置,再对称翻转。- 算法时间复杂度O(n)
- 算法二思想:
本算法来自Leetcode大佬们,详细的过程见另一篇文章Leetcode 48. 旋转图像 C语言解答- 算法时间复杂度O(n)
void swap(int* a, int* b){
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
void rotate(int** matrix, int matrixRowSize, int *matrixColSizes) {
int i = 0, j = 0;
for(i = 0; i < matrixRowSize; i++) {
for(j = 0; j < i; j++) {
swap(&matrix[i][j], &matrix[j][i]);
}
}
for(i = 0; i < matrixRowSize; i++) {
for(j = 0; j < matrixRowSize / 2; j++) {
swap(&matrix[i][j], &matrix[i][matrixRowSize - 1 - j]);
}
}
}
void rotate(int** matrix, int matrixRowSize, int *matrixColSizes) {
int temp, i, j;
for(int internal = matrixRowSize; internal >= 2; internal -= 2){
j = (matrixRowSize - internal) / 2;
for(i = j; i < (matrixRowSize + internal) / 2 - 1; i++){
temp = matrix[i][j];
matrix[i][j] = matrix[matrixRowSize - j - 1][i];
matrix[matrixRowSize - j - 1][i] = matrix[matrixRowSize - i -1][matrixRowSize - j - 1];
matrix[matrixRowSize - i -1][matrixRowSize - j - 1] = matrix[j][matrixRowSize - i -1];
matrix[j][matrixRowSize - i -1] = temp;
}
}
}