Leetcode刷题每日总结:2、3、124

2. 两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

思路:加法模拟;拿到这两个链表,如示例所给数据,我将每一位分别相加再存入新的链表中,比如第一个链表中的十位是4,第二任个链表中的十位是6,将两个数字相加,由于进位原因我们要定义一个变量存储加和,将加和模上10取个位的0存入新链表中,再将加和除以10保存进位数字,最后将剩余加和存入链表中。

解法:创建一个整形相加和,一个新链表,还有一个指向新链表表头的指针。首先遍历条件:当两个链表不为空时或者加和不为0时,给新链表赋空间,遍历链表,各判断两个是否为空,将非空的链表中的对应数字加入到加和上,处理加和,存入新链表,循环结束,新链表尾赋空,返回标记指针。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    int cnt = 0;        //对位相加和
    struct ListNode *pnode = (struct ListNode*)malloc(sizeof(struct ListNode)); //存放新的求和
    struct ListNode *phead = pnode;     //指向求和链表的头指针
    struct ListNode *pdel;
    while(l1 != NULL || l2 != NULL || cnt != 0) //循环条件:两个链表非空 对位相加和有进位
    {
        pnode->next = (struct ListNode*)malloc(sizeof(struct ListNode));    //malloc
        pnode = pnode->next;
        //如果两个链表上还有数字则相加:
        if(l1 != NULL)
        {
            cnt += l1->val;
            l1=l1->next;
        }
        if(l2 != NULL)
        {
            cnt += l2->val;
            l2=l2->next;
        }
        //将相加到的和取余得到一位存入ponde中
        pnode->val = cnt%10;
        cnt = cnt/10;   //取相加和的最后一位
    }
    pnode->next = NULL;
    phead = phead->next;    //指向pnode的真实头指针;
    free(pdel);     //删除假的头指针
    return phead;
}

3. 无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

思路:’滑动块‘与哈希细想;如示例一,有多个符合题意的子串长度都为3,如'abc','bca',...如果强行遍历添加循环条件可能会导致时间复杂度过高,引起超时。所以将时间转化空间,遍历字符串,把没标记的a位置标记,再把b,c标记,再后面由于a位置已经标记,所以表示已经出现过,所以要把该字串的初始位置记录并后移,还有记录当前子串长度,每加入一个未标记过的字符,将长度加一。如示例3,遍历字符串,记录初始位置为0,p位置标记,长度加1,w位置标记,长度加一,w位置已标记,将记录位置后移至新的w,还要重新计算子串长度,继续此过程,直至遍历完比较出最大值为止。

解法:定义子串初始位置,子串长度值,最大比较值,字符位置记录数组。遍历字符串,判断字符是否标记,若为标记,则标记,并将子串长度加一,若已标记,则将子串初始位置后移到已标记字符记录位置的后一位更新记录位置,并重新计算子串长度值,比较符合题意的子串长度值,返回最大值。

int lengthOfLongestSubstring(char * s){
    int i,j;
    int start = 0;  //初始位置
    int index[200] ;    //记录位置
    int count =0 ;  
    int max = 0;    
    memset(index,-1,sizeof(index));
    for(i=0;i<strlen(s);i++) 
    {
        if(index[s[i]] >= start) //如果该位置的首次出现位置大于 初始位置,一开始是-1(没有)
        {
            start = index[s[i]] + 1;    //将子串 初始位置 向后移一位,
            count = i - start;          //计算当前 子串 长度 
        }
        index[s[i]] = i;    //把字符对应位置存入数组,
        count++;    
        if(count > max) //比较最大子串长度
        {
            max = count;
        }
    }
    return max;
}

124. 二叉树中的最大路径和

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

示例 1:

输入: [1,2,3]

       1
      / \
     2   3

输出: 6

示例 2:

输入: [-10,9,20,null,null,15,7]

   -10
   / \
  9  20
    /  \
   15   7

输出: 42

思路:递归。在该二叉树中找到任意路径,使权值最大。如示例一,路径即为树本身,变例1:如果将根节点的1换为-1,那么最大路径仍然是这条,只不过最大值为5.   变例2:将根节点换为-3,那么最大路径显然是右节点3,我首先拿到根节点,我们知道在二叉树选取路径中选择了一个节点,另一个节点则不可在选,在这个子树(二叉树)中,根节点值-3与左节点相加为-1,右节点相加为0,而这子树(二叉树)总和为2,而相比右节点的3小,所以选右节点 因此在树中我们要少选择带负的节点(子树),将变例2带入到示例2,根节点-10,左负右正,所以选择右子树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 #define imin 0x80000000
class Solution {
public:
    int maxPathSum(TreeNode* root) {
        if(!root) return 0;
        int ans = imin; //结果
        findmax(root,ans);  //最大路径函数
        return ans;
    }
private:
int findmax(struct TreeNode *root,int& ans)
{
    if(!root) return 0 ;
    int l = max(0,findmax(root->left,ans)); //取根左边大值->递归
    int r = max(0,findmax(root->right,ans));//取根右边大值->递归
    int sum = l+r+root->val;    //得到子树左右总和
    ans = max(ans,sum);     
    return max(l,r)+root->val;      //取左/右最大值
}
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值