Day27

今日份:

1.已知一棵二叉树,求它每层结点的平均值。

感觉也也是一道基础高危题,在层次遍历上稍微做了一下调整,在正常层次遍历的基础上多加入一个队列,用于记录每层结点的个数,和计算每层各结点的数值和。

List<double> AverageTree(Tree root)
{
    if(root == null)
    {
        return null;
    }
    List<double> result = new List<double>();
    Queue q = new Queue();
    q.Enqueue(root);
    while(q.Any())
    {
        Queue tmp = new Queue();
        int sum = 0;
        int count = 0;
        while(q.Any())
        {
            Tree t = (Tree)q.Dequeue();
            sum += t.val;
            count++;
            if(t.left != null)
            {
                tmp.Enqueue(t.left);
            }
            if(t.right != null)
            {
                tmp.Enqueue(t.right);
            }
        }
        result.Add(sum * 1.0 / count);
        q = tmp;
    }
    return result;
}

2.这里写图片描述

这道题我用了2个函数辅助求左右子树的和以及差,也是写了好多行(lll¬ω¬),而且还是看了提示才明白题的意思,所以为了加深印象,把自己写的难看的但便于自己理解的代码和别人写的好看的代码都记下

自己麻烦的做法:

int FindTilt(Tree root)
{
    //主函数
    if(root == null)
    {
        return 0;
    }
    return Minus(root.left) + Minus(root.right) + Math.Abs(Plus(left) - Plus(right));
}
int Plus(Tree root)
{
    //求树的各结点和
    if(root == null)
    {
        return 0;
    }
    return root.val + Plus(root.left) + Plus(root.right);
}
int Minus(Tree root)
{
    //求树的每层结点的差的和
    if(root = null)
    {
        return 0;   
    }
    int minusSum = 0;
    Queue q = new Queue();
    q.Enqueue(root);
    while(q.Any())
    {
        int lv = 0;
        int rv = 0;
        Tree tmp = (Tree)q.Dequeue();
        if(tmp.left != null)
        {
            q.Enqueue(tmp.left);
            lv = Plus(tmp.left);
        }
        if(tmp.right != null)
        {
            q.Enqueue(tmp.right);
            rv = Plus(tmp.right);
        }
        minusSum += Math.Abs(lv - rv);
    }
    return minusSum;
}

别人的:

int sum = 0;
int FindTilt(Tree root)
{
    //主函数
    if(root == null)
    {
        return 0;
    }
    Calculate(root);
    return sum;
}
int Calculate(Tree item)
{
    if(item == null)
    {
        return 0;
    }
    int lv = Calculate(item.left);
    int rv = Calculate(item.right);
    sum += Math.Abs(lv - rv);
    return lv + rv + item.val;
}

进而我发现我自己写的Minus版本完全就可以用主函数的递归替代了,因为Minus里进行的操作和主函数最后返回的都是“左减右的绝对值”,所以把Minus删掉,保留Plus函数,主函数可以直接写成:

int FindTilt(Tree root)
{
    if(root == null)
    {
        return 0;
    }
    return FindTilt(root.left)+FindTilt(root.right)+Math.Abs(Plus(root.left)-Plus(root.right));
}

这样看起来更舒服一些。

3.这里写图片描述

“易位构词游戏,判断t是不是s的易位词”,这道题我做的时候用了Dictionary,很浪费空间的把两个字符串倒到了两个dictionary里,然后再比较两个dictionary。而看了别人的代码发现用两个大数组就够了(lll¬ω¬)。。。

自己的:

bool IsAnagram(string s, string t)
{
    if(s == null || t == null)
    {
        return false;
    }
    if(s.Length != t.Length)
    {
        return false;
    }
    Dictionary<char, int> dicS = new Dictionary<char, int>();
    Dictionary<char, int> dicT = new Dictionary<char, int>();
    //返回true的条件为两字符串长度相等,其中各字母相同且数量相等,所以建立了字符对应个数的字典。
    for(int i = 0; i < s.Length; i++)
    {
        if(dicS.ContainsKey(s[i]))
        {
            dicS[s[i]]++;
        }
        else
        {
            dicS.Add(s[i], 1);
        }
    }
    for(int i = 0; i < t.Length; i++)
    {
        if(dicT.ContainsKey(t[i]))
        {
            dicT[t[i]]++;
        }
        else
        {
            dicT.Add(t[i], 1);
        }
    }
    foreach(KeyValuePair<char, int> kvpS in dicS)
    {
        //如果t中没有s中的某个字母返回false
        if(!dicT.ContainsKey(kvpS.Key))
        {
            return false;
        }   
        //如果t中某个字母的个数和s中的不相等返回false
        if(dicT[kvpS.Key] != kvp.Value)
        {
            return false;
        }
    }
    return true;
}

别人的:

bool Anagram(string s, string t)
{
    if(s == null || t == null)
    {
        return false;
    }
    if(s.Length != t.Length)
    {
        return false;
    }
    char[] arr1 = new char[256];
    char[] arr2 = new char[256];
    for(int i = 0; i < s.Length; i++)
    {
        arr1[s[i]]++;
        arr2[t[i]]++;
    }
    return new string(arr1).Equals(new string(arr2));
}

然后发现,如果用排序的话写起来更简单( ╯□╰ ) (怎么能把排序忘了呢。。。):

bool Anagram(string s, string t)
{
    char[] sc = s.ToCharArry();
    char[] tc = t.ToCharArry();
    Array.Sort(sc);
    Array.Sort(tc);
    return Array.Equals(sc, tc);
}

4.找出字符串s中第一个没有重复字符的字符序号,没有则返回-1(假设字符串只包含小写字母)

又是一道让我写复杂的题,也是用了dictionary和List,其实只要一个数组就好了

int FindUniqueCharacter(string s)
{
    if(s == null)
    {
        return -1;
    }
    int[] freq = new int[26];
    for(int i = 0; i < s.Length; i++)
    {
        ++freq[s[i] - 97];
    }
    for(int i = 0; i < s.Length; i++)
    {
        if(freq[s[i] - 97] == 1)
        {
            return i;
        }
    }
    return -1;
}
### 关于亿学编程爬虫 Day27 作业的分析与解答 在亿学编程爬虫 Day27 的课程中,通常会涉及更复杂的爬虫任务,例如定时爬取、多线程或异步爬取等[^1]。以下是一个可能的示例代码和相关技术解析,帮助理解如何实现这些功能。 #### 示例代码:基于 Scrapy 框架的定时爬取任务 Scrapy 是一个强大的网络爬虫框架[^2],可以用来构建高效的爬虫系统。结合定时任务调度工具如 `APScheduler`,可以实现定时爬取的功能。 ```python from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings from apscheduler.schedulers.twisted import TwistedScheduler # 定义爬虫启动函数 def start_spider(): process = CrawlerProcess(get_project_settings()) process.crawl('example_spider') # 替换为实际的爬虫名称 process.start() # 创建调度器并添加定时任务 scheduler = TwistedScheduler() scheduler.add_job(start_spider, 'interval', hours=1) # 每小时运行一次 scheduler.start() ``` #### 多线程爬取示例 对于简单的多线程爬取任务,可以使用 Python 的 `threading` 模块[^3]。以下是一个基础的多线程爬取代码示例: ```python import threading import requests def fetch(url): response = requests.get(url) print(f"Fetched {url}, Status Code: {response.status_code}") urls = ["http://example.com", "http://example.org", "http://example.net"] threads = [] for url in urls: thread = threading.Thread(target=fetch, args=(url,)) threads.append(thread) thread.start() for thread in threads: thread.join() ``` #### 分布式爬取与增量更新机制 在大规模爬虫系统中,分布式爬取和增量更新是常见需求。可以通过 Redis 或其他消息队列工具来管理任务分发和状态同步[^1]。以下是一个基于 Redis 的简单任务队列示例: ```python import redis import json # 初始化 Redis 连接 r = redis.Redis(host='localhost', port=6379, db=0) # 发布任务到队列 task = {"url": "http://example.com", "priority": 1} r.lpush("crawl_queue", json.dumps(task)) # 从队列中获取任务 while True: task_json = r.rpop("crawl_queue") if not task_json: break task = json.loads(task_json) print(f"Processing task: {task}") ``` #### 技术扩展与优化方向 - **反爬策略**:通过设置请求头、使用代理 IP 和随机化 User-Agent 等方式避免被目标网站封禁[^1]。 - **增量更新**:利用哈希值或时间戳记录已爬取的内容,减少重复抓取[^1]。 - **性能优化**:结合异步 IO(如 `asyncio`)和多线程技术提升爬取效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值