leetcode初级总结(一)数组

数组基础知识回顾

数组的基础知识主要有声明与引用,赋值、遍历等,因为较常用,基本上都很熟悉,简单回顾一下动态数组的声明与引用。
静态数组在声明的时候就确定了数组的大小,并且不能修改,在实际中,经常会遇到这样一种情况,所需的空间取决于实际输入的数据,而无法预先确定,对于这种问题,可以使用动态数组来解决。
1、动态分配
一维数组:

int *array; // 数组指针
int arrLen;  // 数组长度
int i; // 数组下标
array = (int*)malloc( arrLen*sizeof(int) );

二维数组:

#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
	int i, row, column;
	int **arr;
 
	while (scanf("%d %d", &row, &column) != EOF) {
		arr = (int **)malloc(sizeof(int *) * row); // 分配所有行的首地址
		for (i = 0; i < row; i ++) { // 按行分配每一列
			arr[i] = (int *)malloc(sizeof(int) * column);	
		}
 
		// 释放开辟的二维数组空间
		for (int i = 0; i < row; ++i)
		{
			free(*(arr + i));
		}
	}
 
	return 0;
}

2、引用
使用数组下标,从0到n-1(n为数组长度)

回顾数组初级部分题

1、从排序数组中删除重复项
  • 题目说明:
    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

  • 解题思路:
    由于数组有序,使用两个指针从相邻的两个元素开始检查,如果相邻的两个元素不相同,就保留较小下标的元素值,将两个指针同时后移一位;如果两个元素值相同,保留较小下标元素的值,并将该指针向后移一位,另一个指针向后移动到与与该元素不相同为止;较大的指针指向数组的尾端就停止。

  • 代码:

int removeDuplicates(int* nums, int numsSize) {
  
    if (nums == NULL || numsSize <= 1) 
        return numsSize;
    
    int i,j;
    
    for (i=0,j=1; j<numsSize; ) {
        if (nums[i] != nums[j]) {
            nums[i+1] = nums[j];
            i++;
            j++;
            continue;
        } else {
            j++;
            continue;
        }
    }
    return i+1;
}
2、买卖股票的最佳时机||(leetcode122)
  • 题目说明:
    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
    设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
  • 解题思路
    感觉这道题和数组的关系不大,解题的关键在与解题思路,用到的是贪心算法的思想,尽可能的获取当前最大的利益。
  • 代码
int maxProfit(int* prices, int pricesSize) {
    int i, profit=0;
    for (i=0; i<pricesSize-1; i++) {
        if (prices[i+1] > prices[i])
            profit += prices[i+1] - prices[i];
        
    }
    return profit;
}
3、旋转数组
  • 题目说明
    给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
  • 解题思路
    这道题在于对数组元素的操作,按照题目要求做即可,要求向右移动k个位置,可以分k次移动,每次向右移动一个位置,在移动的过程中,注意特殊位置的值。
  • 代码
void rotate(int* nums, int numsSize, int k) {   
    int i, j;
    int flag_value;
    int temp;
    
    /* 排除异常情况 */
     if(k > numsSize)
     {
         k = k % numsSize;
     }
    else if(k == 0)
    {
        return;
    }
    
    /* 循环移位 */
    while(k>0)
    {
        temp = nums[0];
        for(i = numsSize - 1; i >= 0; i--)
        {
            if(i == numsSize - 1)
                nums[0] = nums[i];
            else
                nums[i + 1] = nums[i];
        }
        nums[1] = temp;
        k--;
    }
}
4、存在重复
  • 题目说明
    给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。
  • 解题思路
    取第一个元素和其他元素比较,如果相同,则存在重复,直接返回;如果不相同,则依次取第二个、第三个……,如果取到最后一个还没有,就说明不存在重复的元素。这是一种笨办法。
  • 代码
bool containsDuplicate(int* nums, int numsSize) {

    int i = 0, j = 0;
    for (i=0; i<numsSize-1; i++) {
        for (j=i+1; j<numsSize; j++) {
            if(nums[i]==nums[j])
                return true;
        }
        
    }
    return false;
}
5、只出现一次的数字(leetcode136)
  • 题目说明
    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
  • 解题思路
    我们学过一个运算符(^)它的作用是两个数的二进制中的每一个比特位,形同为0,不同则为1.即(1 ^ 1 = 0,50 ^ 50 = 0,0 ^ 100 = 100),那如果将这组数据每一位都^则最后的出的那个结果就是只出现一次的那个数。
  • 代码
int singleNumber(int* nums, int numsSize) {
    int i;
    int result = nums[0];
    for(i=1; i<numsSize; i++)
    {
        result =result^ nums[i];
    }
    return result;
}
6、两个数组的交集||
  • 题目说明
    给定两个数组,编写一个函数来计算它们的交集。
  • 解题思路
    先将两个数组排序,然后比较。
  • 代码
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    if(nums1Size==0||nums2Size==0)
        return NULL;
    sort(nums1,nums1Size);
    sort(nums2,nums2Size);
    int *res,i,j;
    res=(int *)malloc(sizeof(int)*nums1Size);
    *returnSize=0;
    for(i=0,j=0;i<nums1Size&&j<nums2Size; )
    {
        if(nums1[i]<nums2[j])
            i++;
        else if(nums1[i]==nums2[j])
        {
            res[(*returnSize)++]=nums1[i];
            i++;
            j++;
        }
        else
            j++;
    }
    return res;
}



//冒泡排序
void sort(int* nums, int numsSize)
{
    int i,j;
    for(i=numsSize-1; i>0; --i)
    {
        for(j=0; j<i; j++)
        {
         if(nums[j]>nums[j+1])   
         {
             int temp = nums[j];
             nums[j] = nums[j+1];
             nums[j+1] = temp;
         }
        }
    }
}


7、加一(leetcode66)
  • 题目说明
    给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
    最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
  • 解题思路
    从最低位加,满10进一。
  • 代码
/**
 * Return an array of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* plusOne(int* digits, int digitsSize, int* returnSize) {
    
    int k = 1, i,n=0;
    for(i = 0;i<digitsSize;i++)
    {
        if(digits[i]==9)
            n++;
    }
    if(n==digitsSize)
    {
        digits[0] = 1;
        digitsSize++;
        for(i=1;i<digitsSize;i++)
            digits[i]=0;
    }
    else
    {
         for(i=digitsSize-1; i>=0; i--)
    {
        if((digits[i]+k)>9)
        {
            digits[i] = digits[i]+k-10;
            continue;
        }
        else
        {
            digits[i] = digits[i]+k;
            k = 0;
        }
    }
    }
        
   *returnSize=digitsSize;
    return digits;
    
    
}


8、移动零(leetcode283)
  • 题目说明
    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
  • 解题思路
    解法1:
    从头开始遍历数组,当遇到数组中不为0的数字时,就把它们按顺序保存在数组里,跳过0,最后在数组后把0补上
    解法2:
    从头开始遍历数组,用变量cnt_zeros记录数组中0的个数,当遇到数组中为0的数时cnt_zeros加1,当遇到不为0的数时,将它们移动,它们前面有几个0就移动几步。
  • 代码
//解法1
void moveZeroes(int* nums, int numsSize) {
						int i,len=0;
						for(i=0;i<numsSize;i++){
								if(nums[i]!=0){
										nums[len]=nums[i];
										len++;
								}
						}
						for(i=len;i<numsSize;i++)
								nums[i]=0;
				}
//解法2
void moveZeroes(int* nums, int numsSize) {
									int i = 0;
									int cnt_zeros = 0;
									for(;i<numsSize;i++) {
											if(nums[i]==0) 
													cnt_zeros++;
											else if (cnt_zeros > 0){
													nums[i-cnt_zeros] = nums[i];
													nums[i] = 0;
											}                        
									}
							}
9、两数之和
  • 题目说明
    给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
  • 解题思路
    给定一个数,找另一个数,也是笨办法,注意static
  • 代码
int* twoSum(int* nums, int numsSize, int target) {
    
    int i,j = 0;
    static int twoSubscript[2];
    
    for(i=0 ;i<numsSize; i++)
    {
              for(j=i+1 ;j<numsSize ;j++)
              {
                  if(nums[i]+nums[j]==target)
                  {
                      twoSubscript[0]=i;
                      twoSubscript[1]=j;
                      return twoSubscript;
                  }
                                   
              }
    }
    
    return twoSubscript;
    
}
10、有效的数独(leetcode36)
  • 题目说明
    判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
    数字 1-9 在每一行只能出现一次。
    数字 1-9 在每一列只能出现一次。
    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
  • 解题思路
    按照要求,判断,二维数组,操作有点复杂
  • 代码
bool isValidSudoku(char** board, int boardRowSize, int boardColSize) {
    int i, j, k; 
    
    /* 判断每行数组中的值是否只出现一次 */
    for(k = 0; k < boardRowSize; k++)
    {
        for(i = 0; i < boardColSize - 1; i++)
        {
            for(j = i + 1; j < boardColSize; j++)
            {
                if(board[k][i] == '.')
                    break;
                else if(board[k][j] == '.')
                    continue;
                else if(board[k][i] == board[k][j])
                    return false;
            }
        }
    }
    
    
    /* 判断每列数组中的值是否只出现一次 */
    for(k = 0; k < boardColSize; k++)
    {
        for(i = 0; i < boardRowSize - 1; i++)
        {
            for(j = i + 1; j < boardRowSize; j++)
            {
                if(board[i][k] == '.')
                    break;
                else if(board[j][k] == '.')
                    continue;
                else if(board[i][k] == board[j][k])
                    return false;
            }
        }
    }
    
    /* 判断3x3矩阵中的值是否只出现一次 */
    int a = 0, b = 0, c = 0, d = 0;
    int row = 0, col = 0;
    int num;
    for(num = 0; num < 9; num++)
    {
        for(a = row; a < 3 + row; a++)
        {
            for(b = col; b < 3 + col; b++)
            {
                /* 判断值为.,则判断下一个 */
                if(board[a][b] == '.')
                {
                    continue;
                }
                /* 判断3x3矩阵是否有相等的值 */
                for(c = 0 + row;c < 3 + row; c++)
                {
                    for(d = 0 + col; d < 3 + col; d++)
                    {
                        if(board[c][d] == '.')
                            continue;
                        else if((a != c) && (b != d) && (board[a][b] == board[c][d]))
                            return false;
                    }
                }
            }
        }
        /* 移动至下一个3x3矩阵 */
        col += 3;
        if(col >= 9)
        {
            col = 0;
            row += 3;
        }
    }

    return true;
}

11、旋转图像
  • 题目说明
    给定一个 n × n 的二维矩阵表示一个图像,将图像顺时针旋转 90 度。
  • 解题思路
    找元素旋转前后的规律
  • 代码
void rotate(int** matrix, int matrixRowSize, int *matrixColSizes) {
    int i, j;
    int n = matrixRowSize;
    
    for (i=0; i<n/2; i++) {
        for(j=i; j<n-1-i; j++) {
            int temp = matrix[i][j];
            matrix[i][j] = matrix[n-1-j][i];
            matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
            matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
            matrix[j][n-1-i] = temp;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值