目录
1.岛屿的最大面积
【题目】
【分析】dfs
//法1
int fun(int **grid, int gridSize, int *gridColSize, int r, int c){
if ( r < 0 || r >= gridSize || c < 0 || c >= gridColSize[0] || !grid[r][c]) {
return 0;
}
grid[r][c] = 0; //计算过即清零 减少计算次数
return 1 + fun(grid,gridSize,gridColSize,r + 1,c) +
fun(grid,gridSize,gridColSize,r - 1,c) +
fun(grid,gridSize,gridColSize,r,c + 1) +
fun(grid,gridSize,gridColSize,r,c - 1);
}
int maxAreaOfIsland(int** grid, int gridSize, int* gridColSize){
int ans, max = 0;
int i = 0, j;
for(i; i < gridSize; i++)
for(j = 0; j < gridColSize[0]; j++){ //千万记得j = 0 写在里面!!
ans = fun(grid,gridSize,gridColSize,i,j);
max = max > ans ? max : ans;
}
return max;
}
---------
//法2
int dfs(int** grid, int gridSize, int* gridColSize, int i, int j) {
if (i < 0 || j < 0 || i == gridSize || j == *gridColSize || grid[i][j] == 0) {
return 0;
}
grid[i][j] = 0;
int ans = 1;
int x[4] = {0, -1, 0, 1};
int y[4] = {-1, 0, 1, 0};
for (int k = 0; k < 4; ++k) {
ans += dfs(grid, gridSize, gridColSize, i + x[k], j + y[k]);
}
return ans;
}
int maxAreaOfIsland(int** grid, int gridSize, int* gridColSize){
int ans = 0;
for (int i = 0; i < gridSize; ++i) {
for (int j = 0; j < *gridColSize; ++j) {
int t = dfs(grid, gridSize, gridColSize, i, j);
ans = ans > t ? ans : t;
}
}
return ans;
}
2.合并二叉树
【题目】
【分析】深度优先搜索
struct TreeNode* mergeTrees(struct TreeNode* root1, struct TreeNode* root2){
if(!root1){
return root2;
}
if(!root2){
return root1;
}
struct TreeNode* merge=malloc(sizeof(struct TreeNode));
merge->val=root1->val+root2->val;
merge->left=mergeTrees(root1->left,root2->left);
merge->right=mergeTrees(root1->right,root2->right);
return merge;;
}
3.填充每一个节点的下一个右侧指针
【题目】
【分析】
法1:递归
void connectTwoNode (struct Node* a, struct Node* b){
if (a == NULL || b == NULL) return;
a->next = b;
connectTwoNode(a->left,a->right); //连接a子树的左右结点
connectTwoNode(b->left,b->right); //连接b子树的左右结点
connectTwoNode(a->right,b->left); //连接相邻子树的相邻结点
}
struct Node* connect(struct Node* root) {
if (root == NULL) return NULL;
connectTwoNode(root->left,root->right);
return root;
}
法2:dfs递归
void dfs(struct Node *root)
{
if (root == NULL)
return; // dfs退出条件
if (root->left)
{// 左子结点的next比较容易
root->left->next = root->right;
}
if (root->right)
{// 右子结点稍微多想一点,利用父节点的next
if (root->next == NULL)
{
root->right->next = NULL;
}
else
{
root->right->next = root->next->left;
}
}
dfs(root->left);
dfs(root->right);
}
struct Node *connect(struct Node *root)
{
if (root == NULL)
return NULL;
root->next = NULL;
dfs(root);
return root;
}
法3:直接next指针递归
struct Node* connect(struct Node* root)
{
if(root == NULL || root->left== NULL)
{
return root;
}
//直接的利用next指针
root->left->next = root->right;
if(root->next)
{
root->right->next = root->next->left;
}
connect(root->left);
connect(root->right);
return root;
}
4.打家劫舍(动态规划)
【题目】
【分析】
int rob(int* nums, int numsSize){
if(numsSize==1){
return nums[0];
}//如果只有一个元素,就可以直接输出
int dp[numsSize];
//定义一个数组dp来记录走到当前时可以拿的最大数之和
dp[0]=nums[0];
dp[1]=fmax(nums[0],nums[1]);
//在dp[1]时就应该考虑nums[0]和nums[1]拿哪一个的问题了,因为dp记录的是最大值,
//nums[0]和nums[1]只能拿一个所以要进行一次比较
for(int i=2;i<numsSize;i++){
dp[i]=fmax(dp[i-2]+nums[i],dp[i-1]);
//由于在dp[i]时,你不能拿(dp[i-1]+nums[i])因为dp[i-1]中可能记录了nums[i-1]
//所以只有拿(dp[n-2]+nums[i])和继承dp[i-1]这两种选择,取大值即可
}
return fmax(dp[numsSize-2],dp[numsSize-1]);
//输出时不能忘了比较一下dp[numsSize-2]和dp[numsSize-1]因为这两个数是没有比较过的
}
5.三角形最小路径和(动态规划)
【题目】
【分析】
int minimumTotal(int** triangle, int triangleSize, int* triangleColSize){
int dp[triangleSize][triangleSize];
//创建一个可以存放所有路径的空间
memset(dp,0,sizeof(dp));
//初始化该空间,使初值都为0
dp[0][0]=triangle[0][0];
//给dp空间的第一个空间赋值
for(int i=1;i<triangleSize;i++){
dp[i][0]=dp[i-1][0]+triangle[i][0];
//因为最左边和别的点不一样,最左边只能通过一个点赋值,所以就当前路径大小等于上面的点加当前的点
for(int j=1;j<i;j++){
dp[i][j]=fmin(dp[i-1][j-1],dp[i-1][j])+triangle[i][j];
//由于不是最左的点,所以有两条路可以选,比较一下那一条路更小,再加上当前路
}
dp[i][i]=dp[i-1][i-1]+triangle[i][i];
//出循环后最右边的和最左边的点一样,都只有一个点能够给它赋值,所以不需要比大小,
//且如果把最右的点加入会越界
}
int ans=dp[triangleSize-1][0];
//创建一个变量用来存放答案,由于所有尽可能小的路径都在最后一排了所以从最后一排找就可以
//所以ans的初始值为最后一排的最左边
for(int i=1;i<triangleSize;i++){
ans=fmin(ans,dp[triangleSize-1][i]);
//通过比较得出最小的路径
}
return ans;
}
6.组合
【题目】给定两个整数 n
和 k
,返回范围 [1, n]
中所有可能的 k
个数的组合。
你可以按 任何顺序 返回答案。
【分析】C++
回溯法
在这里要定义两个全局变量,一个用来存放符合条件单一结果,一个用来存放符合条件结果的集合。还需要一个参数,为int型变量startIndex,这个参数用来记录本层递归的中,集合从哪里开始遍历(集合就是[1,...,n] )
class Solution {
private:
vector<vector<int>> result; // 存放符合条件结果的集合
vector<int> path; // 用来存放符合条件结果
void backtracking(int n, int k, int startIndex) {
if (path.size() == k) {
result.push_back(path);
return;
}
for (int i = startIndex; i <= n; i++) {
path.push_back(i); // 处理节点
backtracking(n, k, i + 1); // 递归
path.pop_back(); // 回溯,撤销处理的节点
}
}
public:
vector<vector<int>> combine(int n, int k) {
result.clear(); // 可以不写
path.clear(); // 可以不写
backtracking(n, k, 1);
return result;
}
};
剪枝优化:
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置
7.存在重复元素
【题目】
【分析】
1.先排序在比较
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);
for (int i = 0; i < numsSize - 1; i++) {
if (nums[i] == nums[i + 1]) {
return true;
}
}
return false;
}
法2:哈希表
直接 set 记录是否出现过
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
unordered_set<int> s;
for(int i:nums){
if(s.count(i)){
return true;
}
s.insert(i);
}
return false;
}
};
8.移除元素
【题目】
【分析】
int removeElement(int* nums, int numsSize, int val) {
int left = 0;
for (int right = 0; right < numsSize; right++) {
if (nums[right] != val) {
nums[left] = nums[right];
left++;
}
}
return left;
}
9.Pow(x,n )
【题目】
【分析】
double myPow(double x, int n){
if(n==0){
return 1;
}
if(n==1){
return x;
}
if(n==-1){
return 1/x;
}
if(n%2!=0){
return x*myPow(x,n-1);
}else{
return myPow(x*x,n/2);
}
}
10.数组加1
【题目】
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头
【分析】
从后向前对数组进行遍历,若该元素为9,则继续向后遍历;否则,将该元素加一,返回数组长度不变返回数组,
若遍历到最后一个元素依然需要进位,创建一个新的数组返回最后的值,将新数组的第一位置为1
int* plusOne(int* digits, int digitsSize, int* returnSize){
for(int i = digitsSize - 1;i >= 0;i--){
if(digits[i] == 9)
digits[i] = 0;
else{
digits[i]++;
*returnSize = digitsSize;
return digits;
}
}
*returnSize = digitsSize + 1;
int *ret = (int*)malloc(sizeof(int)*(digitsSize + 1));
memset(ret,0,sizeof(int)*(digitsSize + 1));
ret[0] = 1;
return ret;
}