Day28

本文分享了几道算法题的解题思路,包括构建最大二叉树、字符串分组、计算数字中1的个数及查找数组中的重复数字。通过递归与数组操作等技巧解决了这些问题。

啊 明天假期就结束了,希望能尽快找到一份满意的工作,一直这样没有直接收入很不安啊,这个年过的也并没有很开心,玩的诱惑太大,每天逼自己得写点儿东西出来其实挺压抑的,明天就回去了,可能压抑感能小一些吧,毕竟比老家安静。
>﹏<

今天总算遇到一道答案比我写的方法繁琐多的多的题,嘻嘻:

1.已知一个数组,求建立一棵二叉树,要求二叉树的根节点是数组中的最大数,左子树是其数组中所有左边的元素,右子树是其数组中所有右边的元素,左子树和右子树也遵从第一条条件。

思路:相当于以数组中最大数为界分为左右两部分,然后递归。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode ConstructMaximumBinaryTree(int[] nums) {
        if(nums == null)
        {
            return null;
        }
        int rootV = MaxNum(nums);
        List<int> leftNums = new List<int>();
        List<int> rightNums = new List<int>();
        int i = 0;
        int j = nums.Length - 1;
        while(nums[i] != rootV)
        {
            leftNums.Add(nums[i]);
            i++;
        }
        while(nums[j] != rootV)
        {
            rightNums.Add(nums[j]);
            j--;
        }
        TreeNode  t = new TreeNode(rootV);
        if(leftNums.Count != 0)
        {
            t.left = ConstructMaximumBinaryTree(leftNums.ToArray());
        }
        else
        {
            t.left = null;
        }
        if(rightNums.Count != 0)
        {
            rightNums.Reverse();
            t.right = ConstructMaximumBinaryTree(rightNums.ToArray());
        }
        else
        {
            t.right = null;
        }
        return t;
    }

    public int MaxNum(int[] nums)
    {
        int max = nums[0];
        for(int i = 1; i < nums.Length; i++)
        {
            if(nums[i] > max)
            {
                max = nums[i];
            }
        }
        return max;
    }
} 

所以说人呐,很多时候就是不能高兴的太早,转身就啪啪打脸,立刻就点开了一道又双叒想复杂的题,而且又是字符串问题( ╯□╰ )。。。

2.已知一个全部由小写字母组成的字符串,求将这个字符串尽可能分成多的组,要求每种字母最多只出现在一个分组中,最后输出各分组的长度。

思路:刚开始想到了需要确定每种字符出现的个数和最后出现的位置,目前来说方向大致是正确的(其实只需要知道每个字母最后出现的位置即可),但是之后就想复杂了,其实到这步已经有分组的雏形了,剩下的只需要堆分组做微调,检查当前字母之后是不是有后续字母还和它属于同一组,只要取位置比较靠后(序号比较大)的那个就好了。

List<int> PartitionLabels(string s)
{
    int[] last = new int[26];
    //记录s种每种字母最后出现的位置
    for(int i = 0; i < s.Length; i++)
    {
        last[(int)s[i] - 98] = i;
    }

    //j用来筛选同一组种位置比较靠后的字母,anchor用来定位下一组的第一个字母
    int j = 0; 
    int anchor = 0;
    List<int> result = new List<int>();
    for(int i = 0; i < s.Length; i++)
    {
        j = Math.Max(j, last[(int)s[i] - 98]);
        if(j == i)
        {
            result.Add(i - anchor + 1);
            anchor = i + 1;
        }
    }
    return result;
}

3.已知一个非负整数num,求从0到num的每个数中1的个数

正常时间复杂度为O(num * sizeof(num))的方法很容易想到:

int[] CountingBits(int num)
{
    int[] result = new int[num + 1];
    for(int i = 0; i <= num; i++)
    {
        int n = i;
        int count = 0;
        while(count < n)
        {
            n &= n-1;          //每次舍弃最后边的1
            count++;
        }
        result[i] = count;
    }
}

但是题目要求时间复杂度不能超过O(n)

int[] CountingBits(int num)
{
    int[] result = new int[num + 1];
    for(int i = 0; i <= num; i++)
    {
        result[i] = result[i>>1] + (i&1);
    }
    return result;
}

4.已知一个长度为n的数组,数组中的每个元素都是1到n的正整数,其中有些数字在数组中出现了2次,求这些数字。要求时间复杂度不超过O(n),不用多余的空间。

这道题和Day24记录的第三道题很像,思路都属于将已知数组重新散列

List<int> FindDuplicateNum(int[] nums)
{
    List<int> result = new List<int>();
    for(int i = 0; i < nums.Length; i++)
    {
        int tmp = Math.Abs(nums[i]) - 1;
        if(nums[tmp] < 0)
        {
            result.Add(tmp + 1);
        }
        nums[tmp] = -nums[tmp];
    }
    return result;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值