NO.2 关于remove,append以及移动指针在数组中的运用

本文介绍了使用Python处理数组时,如何运用remove、append及移动指针对数组进行操作。通过两个编程题目的解题过程,阐述了在寻找数组中出现一次的数字以及找到连续正整数序列时的思路。对于第一题,作者对比了使用字典和空列表的优劣,最终选择空列表实现。第二题中,提出了设置上下边界指针的方法,逐步逼近目标序列,实现高效查找。

前言

    今天友做了两道题,边看答案边做的。希望能将自己的思考过程和大家的结果进行记录对比,以便于自己更好的复盘学习。

题目一

    问题描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

    思路描述:一开始我的思路是将数组中的值先放入字典,然后找到相同的就将字典里面的值删除。这样剩下的就是只出现一次的值。为什么会优先考虑字典,是因为考虑字典方便查找的特性。但是后来发现即使有一样的值,也不好定向删除。于是还不如直接用空列表,这样更加方便,完全不需要字典里面的键。字典需要通过键来删除值。

    代码展示:

# -*- coding:utf-8 -*-
class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        # write code here   
        if not array:  #首先判断是不是array
            return 0  #如果不是就返回false
        newarray=[]  #建立一个新的空数组。
        for i in array: #逻辑很简单。如果在数组中的值不在新数组中,那么append该值。如果已经存在了,那么remove这个值。剩下来的就是没有被重复的值。
            if i not in newarray:
                newarray.append(i)  #如果没有在newarray里面,那么append添加该值
            else:
                newarray.remove(I) #如果在的话,这时候正好删除该值。相比字典好的一点是,不需要找到它的键。
        return newarray        #返回结果
        #实际上,异或运算才是这道题考察的核心。也可以用python中的count函数。        
            

    dict删除补充:pop()删除给定键对应的值。如 dict.pop(index)  ;clear()清空字典的内容,dict.clear();popitem()随机删除字典内容,dict.popitem()

>>> dict={}
>>> dict[1]="wo"
>>> dict[2]="ai"
>>> dict[3]="coding"
>>> dict
{1: 'wo', 2: 'ai', 3: 'coding'}
>>> dict.pop(1)
'wo'
>>> dict
{2: 'ai', 3: 'coding'}
>>> dict[4]="chifan"
>>> dict
{2: 'ai', 3: 'coding', 4: 'chifan'}
>>> dict.popitem()
(4, 'chifan')
>>> dict
{2: 'ai', 3: 'coding'}
>>> dict.clear()
>>> dict
{}

题目二

    问题描述:

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

输出描述:

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

    思路描述:我当时的思路非常局限于从数学这个角度去考虑s的n为连续正整数序列,s/n 一定是这连续正整数的中间值。这就得从n为多少去考虑了。假如n为4,找到中间值,左边减去2后面加上2之类的。例如100/8=12.5,那么12.5左边四个数为9 10 11 12 后边四个数为13 14 15 16; 100/5=20,那么20 左边两位为18 19,右边两位为21 22. n分奇偶性~这样考虑就比较复杂了,一是需要将n的边界表示出来,二是在n边界表示出来之后,需要判断是s/n结果是否可满足相加条件。具有可实现性,但是很复杂。

另外一个思路是设置两个指针,一个小的下边界a,和一个大的上边界b。先用一个临时容器将ab之间的值加入到临时容器中,然后计算它们的和,判断和是否于s相同。如果相同,则将临时容器中的结果append到result中,如果不相同,那么分为大于或小于s。如果大于s,那么将a增大。如果小于s,那么将b增大。这样就能不断移动,知道找到所有连续正整数序列。

# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        #连续的序列的话,平均数一定是中间数值的大小。那么就从判断中间数值的大小开始。如果被奇数n整除了,那么则在该平均值的前后加上几个数。被偶数n整除了的话,则在其后加几个值。
        #还有个思路是从左到右相加,如果大于结果,那么左移动,如果小于结果,右移动。
        small = 1   #最小的数
        big = 2    #最大的数
        result = []  #结果容器
        while small < (tsum+1)/2:    #当最小的数小于均值时候,如果最小的比中间值大,那么不可能继续进行了。
            re = [] #临时容器
            res = 0  #结果初设为0
            for i in range(small, big+1):   #在这个下上边界内
                re.append(i)     #将i插入空列表
                res += i   #然后将i的值相加
            if res == tsum:  #判断这个值和是否相同
                result.append(re)  #如果相同,那么将答案插入到结果当中
                small += 1  #此时将小的边界扩大
            elif res > tsum:  #如果结果比s大的话,将边界扩大
                small += 1
            elif res < tsum:  #小的边界扩大之后,结果可能s小,此时增大边界
                big += 1
        return result   #此时已经将很多结果都插入到这个列表当中了
    

总结

[1]:目前这个阶段,能不能快速写出结果是其次的目标,一定得有自己coding的思路,再总结复盘对比别人的思路,这样就能很好的写出答案。

    


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值