啊 明天假期就结束了,希望能尽快找到一份满意的工作,一直这样没有直接收入很不安啊,这个年过的也并没有很开心,玩的诱惑太大,每天逼自己得写点儿东西出来其实挺压抑的,明天就回去了,可能压抑感能小一些吧,毕竟比老家安静。
>﹏<
今天总算遇到一道答案比我写的方法繁琐多的多的题,嘻嘻:
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;
}

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

被折叠的 条评论
为什么被折叠?



