记牛客2018真题笔试刷(一)

目录

最大乘积(贪心,拼多多,中等)

六一儿童节(贪心,拼多多)

彩色的砖块(巧思考,网易)

等差数列(思考,网易)

交错01串(字符串,网易)


 

最大乘积(贪心,拼多多,中等)

题目描述

给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,要求时间复杂度:O(n),空间复杂度:O(1)

输入描述:

输入共2行,第一行包括一个整数n,表示数组长度
第二行为n个以空格隔开的整数,分别为A1,A2, … ,An

输出描述:

满足条件的最大乘积

示例1

输入

4
3 4 1 2

输出

24

思路

看到题没思路。依次取到当前序列中的最大值,取到之后,找次最大值(将最大值从序列中删去,再找最大值),再找次次最大值,求出它们的乘积。接着,按同样方法,再在初始序列中找最小值,次最小值,次次最小值,求它们的乘积,两次结果取最大。

1.这样的做法等同于先把序列排好序,然后,取首尾的值,我们按首来考虑,

如果该序列的最大值为正,并且只有这一个为正,那么首的三个数乘积一定是最大值,因为尾的三个数乘积肯定是负数,其他任意三个数连乘也肯定是负数。

如果该序列的只有首的前两个数为正,那么首三乘积就是负的了,尾三乘积也是负的,到底谁大,就要比比了,因为负数是越往模越大值越小。

如果该序列的至少前三个值正,也需要跟尾三数乘积比比,万一尾三乘积乘出的是个正数,不一定比首三乘积的小。

综上所述,不哔哔了,首三乘积和尾三乘积是主要考虑的对象,中间的元素是不需要考虑的。

2.这里用到了copy的操作,lstcopy=lst[:]是浅拷贝,但并不影响整个结果,这里提个醒。

3.记住序列删除某个指定元素的操作,lst.remove(max)

4.求最大最小值的函数max,min

5.我有个疑问,要求时间复杂度是O(n),那sort()函数排序的时间复杂度竟然这么快啊?

订正:并不是简单的首三乘积和尾三乘积,上面说错了,经过测试发现,分析的思路应该是这样的:如果求最大的乘积,按有正数的情况来考虑,如果,一个按顺序排列后,一般而言,如果比较的数字大于3个,那么:

组合一:最大的三个正数,

组合二:最小的两个负数加最大的一个正数

最大值只会在这两种组合中,出现,想想是不是?

code

版本一

n = int(raw_input().strip())
lst = list(map(int, raw_input().strip().split()))

max1 = max(lst)
lst.remove(max1)
lstcopy = lst[:]
max2 = max(lst)
lst.remove(max2)
max3 = max(lst)

min1 = min(lstcopy)
lstcopy.remove(min1)
min2 = min(lstcopy)
lstcopy.remove(min2)

print(max(max1*max2*max3, min1*min2*max1))

版本二

n = int(raw_input())
nums = map(int,raw_input().split())
nums.sort()
print max(nums[0]*nums[1]*nums[-1],nums[-1]*nums[-2]*nums[-3])

六一儿童节(贪心,拼多多)

题目描述

六一儿童节,老师带了很多好吃的巧克力到幼儿园。每块巧克力j的重量为w[j],对于每个小朋友i,当他分到的巧克力大小达到h[i] (即w[j]>=h[i]),他才会上去表演节目。老师的目标是将巧克力分发给孩子们,使得最多的小孩上台表演。可以保证每个w[i]> 0且不能将多块巧克力分给一个孩子或将一块分给多个孩子。

输入描述:第一行:n,表示h数组元素个数 第二行:n个h数组元素 第三行:m,表示w数组元素个数 第四行:m个w数组元素

输出描述:上台表演学生人数

示例1

输入

3 
 2 2 3
 2
 3 1 

输出

1

思路

我的思路是,将两个序列先升序排好,然后,逐个分布设置两个指针开始比较,a指向小朋友,b指向巧克力,如果当前比较的巧克力可以满足小朋友的需求,就count +=1,然后,将a,b都向后移动,如果b,不满足当前小朋友的需求,那么a不动,b向后移动,依次遍历,直到小朋友序列或者巧克力序列有一个循环完,返回count.

看正确思路,吻合。

code

#-*- coding:utf-8 -*-
def solve():
    n = input()  # 表示h数组元素个数,学生人数
    h = map(int, raw_input().split())  # n个h数组元素,每个学生所需的巧克力
    m = input()  # 表示w数组元素个数,m个巧克力
    w = map(int, raw_input().split())  # m个h数组元素,每个巧克力的重量

    h.sort(reverse=True)  # p
    w.sort(reverse=True)  # k

    k, p, res = 0, 0, 0
    while (k < m and p < n):
        if w[k] >= h[p]:
            res += 1
            k += 1
            p += 1
        else:
            p += 1
    return res

if __name__ == "__main__":
            print(solve())

彩色的砖块(巧思考,网易)

题目描述

小易有一些彩色的砖块。每种颜色由一个大写字母表示。各个颜色砖块看起来都完全一样。现在有一个给定的字符串s,s中每个字符代表小易的某个砖块的颜色。小易想把他所有的砖块排成一行。如果最多存在一对不同颜色的相邻砖块,那么这行砖块就很漂亮的。请你帮助小易计算有多少种方式将他所有砖块排成漂亮的一行。(如果两种方式所对应的砖块颜色序列是相同的,那么认为这两种方式是一样的。)
例如: s = "ABAB",那么小易有六种排列的结果:
"AABB","ABAB","ABBA","BAAB","BABA","BBAA"
其中只有"AABB"和"BBAA"满足最多只有一对不同颜色的相邻砖块。

输入描述:

输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50),s中的每一个字符都为一个大写字母(A到Z)。

输出描述:

输出一个整数,表示小易可以有多少种方式。

示例1

输入

ABAB

输出

2

思路

我的思路是先全排列,然后遍历每个排列,设置一个标识符count为0。每次如果当前元素和后面元素不同就加1,最后,遍历结束后后,如果count = 1 或者count = 0,则再总计数res里加一,统计数量。但这个的思路时间复杂度肯定超。

再看正确的思路,先将序列出现的元素种类统计出来,如果元素种类大于2,怎么排列也无法排成最多只有一对不同颜色的相邻砖块。

如果等于2类,那肯定是只有两种排列可能,

如果只有1类,那不用说了,肯定只有一种。

综上所述,我好傻—  —||。

code

def differentChar(str):
    if str == None or len(str) <= 0:
        return 0

    new_str = []
    for item in str:
        if item not in new_str:
            new_str.append(item)

    if len(new_str) == 1:
        return 1
    elif len(new_str) == 2:
        return 2
    else:
        return 0


if __name__ == "__main__":
    str = raw_input()
    print(differentChar(str))

等差数列(思考,网易)

题目描述

如果一个数列S满足对于所有的合法的i,都有S[i + 1] = S[i] + d, 这里的d也可以是负数和零,我们就称数列S为等差数列。
小易现在有一个长度为n的数列x,小易想把x变为一个等差数列。小易允许在数列上做交换任意两个位置的数值的操作,并且交换操作允许交换多次。但是有些数列通过交换还是不能变成等差数列,小易需要判别一个数列是否能通过交换操作变成等差数列

输入描述:

输入包括两行,第一行包含整数n(2 ≤ n ≤ 50),即数列的长度。
第二行n个元素x[i](0 ≤ x[i] ≤ 1000),即数列中的每个整数。

输出描述:

如果可以变成等差数列输出"Possible",否则输出"Impossible"。

示例1

输入

3 3 1 2

输出

Possible

思路

一看没思路。一看正确的解,想骂人,我主要被困住的地方是:“小易允许在数列上做交换任意两个位置的数值的操作,并且交换操作允许交换多次。”我实在是思考不出来这个条件怎么用,合着对应的就是将数列排下顺序!然后,依次求差,如果差都相等,就是等差数列!

code

a = int(raw_input(""))
b = map(int,raw_input("").split(" "))
c = sorted(b)
res = []
for i in range(len(c)-1):
    res.append(c[i+1]-c[i])
if len(set(res)) == 1:
    print 'Possible'
else:
    print 'Impossible'

交错01串(字符串,网易)

题目描述

如果一个01串任意两个相邻位置的字符都是不一样的,我们就叫这个01串为交错01串。例如: "1","10101","0101010"都是交错01串。小易现在有一个01串s,小易想找出一个最长的连续子串,并且这个子串是一个交错01串。小易需要你帮帮忙求出最长的这样的子串的长度是多少。

输入描述:

输入包括字符串s,s的长度length(1 ≤ length ≤ 50),字符串中只包含'0'和'1'

输出描述:

输出一个整数,表示最长的满足要求的子串长度。

示例1

输入

111101111

输出

3

思路

我的思路是遍历字符串,if:s[i] != s[i+1] ->count += 1,else:  res.append(count),count = 0,最后,把res里保存的最大值输出就行了。

对比一下正确的思路,是吻合的,唯一美中不足的是,我默认的是从0开始累加,正确的是从1开始累加,因为计数长度的确是从1开始计数的。

code

ss = raw_input()
k = 1
K = []
for i in range(0, len(ss)-1):
    if ss[i] != ss[i + 1]:
        k += 1
        K.append(k)
    else:
        k = 1

if K:
    print(max(K))
else:
    print(1)
      

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值