三道头条的算法笔试题

【例1】
给出一个长度为n的数组a1、a2、…、an,请找出在所有连续区间中,区间和最大同时这个区间0的个数小于等于3个,输出这个区间和。

输入:第一行一个正整数n,表示数组长度,1 <= n <= 1000000。
​ 第二行为n个正整数a1 a2 … an,其中-1e9 <= a1,a2,…,an <= 1e9

输出:一个整数

样例:

输入1: 5
1 2 3 4 5
输出1: 15

输入2: 6
15 0 0 0 0 20
输出2: 20

Python实现


n = int(input())
nums = []
for i in range(0,n):
    nums.append(int(input()))
total = [0,0,0]
zero_pos = [-1,-1,-1]
zero_seq = 0
max_ = 0
for i in range(0,n):
    if 0 == nums[i]:
        if zero_seq < 2:
            zero_seq += 1
        else:
            if sum(total) > max_:
                max_ = sum(total)
            temp = total[1:3]
            temp.append(0)
            total = temp
    else:
        total[zero_seq] += nums[i]

if sum(total) > max_:
    max_ = sum(total)
print(max_)

Go实现

package main

import "fmt"

func main() {
	var n int
	fmt.Scanf("%d\n", &n)
	nums := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Scanln(&nums[i])
	}
	total := []int{0, 0, 0}
	zero_index := 0
	max := 0
	for i := 0; i < n; i++ {
		if 0 == nums[i] {
			if zero_index < 2 {
				zero_index++
			} else {
				sum := total[0] + total[1] + total[2]
				if sum > max {
					max = sum
				}
				total = append(total[1:3], 0)
			}
		} else {
			total[zero_index] += nums[i]
		}
	}
	sum := total[0] + total[1] + total[2]
	if sum > max {
		max = sum
	}
	fmt.Println(max)
}

【例2】

给定一个n * m 矩阵 A,矩阵中每个位置 Aij 为一个 16 进制数。

寻找一条从左上角到右下角的路径,每次只能向右或者向下移动,使得路径上所有数字之积在16进制下的后缀0最少。

输入:

第一行: n, m (2 <= n, m <= 1000)
接下来 n 行, 每行 m 个16进制整数, 0 < Aij < 10^9

输出:

第一行:最少后缀0的个数 (10进制)
第二行:路径方案, 从左上角开始, > 代表向右移动,V 代表向下移动。如果有多种方案,输出字典序最小的方案。

样例输入:
3 3
3 2 8
c 8 8
2 a f
样例输出:
1
>>VV

实现

s = input().split()
n = int(s[0])
m = int(s[1])

import itertools
print 

A = []
for i in range(0,n):
    row = []
    s = input().split()
    for j in range(0,len(s)):
        row.append(int(s[j], 16))
    A.append(row)

comb_origin = []
for i in range(0,n+m-2):
    comb_origin.append(i)
    
comb = list(itertools.combinations(comb_origin,m-1)) #右转
best_zeros_nums = -1
best_str = ""
for item in comb:
    STR = ""
    i = 0
    j = 0
    total = A[i][j]
    for seq in range(0, n+m-2):
        if seq in item:
            STR += ">"
            j += 1
        else:
            STR += 'V'
            i += 1
        total = total*A[i][j]
    zeros_nums = 0
    total_hex = str(hex(total))
    for i in range(len(total_hex)-1, -1, -1):
        if total_hex[i] == '0':
            zeros_nums += 1
        else:
            break

    if zeros_nums < best_zeros_nums or best_zeros_nums == -1:
        best_zeros_nums = zeros_nums
        best_str = STR
        
print(best_zeros_nums)
print(best_str)

点评
××input多个数字时,用 input().split()
××排列组合用库itertools.combinations(list, num)
××如果是要排列位置的话,小技巧是,list用一个顺序排列的数组 [0,1,2,3,4…] 这样最后得到的组合结果就是指位置了
××将字符串按照16进制格式转换为int是 int(str, 16)
××将整数转换为16进制字符串 str(hex(int))
××for 倒序循环 i in range(倒序起始点, 倒序终止点, -1) 其中,是开闭区间的,-1是步长

【例3】

给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列。如何分割才能使这m段子序列的和的最大值达到最小?

输入
第一行输入一个整数t,代表有t组测试数据。
每组数据第一行为两个整数n,m分别代表序列的长度和最多可分的段数。
接下来一行包含n个整数表示序列。
0<=n<=50000 1<=m<=n,0<=ai<=2^30。

输出
输出一个整数表示和最大的一段的最小值。

t = int(input())
a = []
m = []
for i in range(0, t):
    temp = input().split()
    n = int(temp[0])
    m_i = int(temp[1])
    m.append(m_i)
    temp = input().split()
    a_i = []
    for j in range(0,len(temp)):
        a_i.append(int(temp[j]))
    a.append(a_i)

for id in range(0, t):
    a_i = a[id]
    m_i = m[id]
    n_i = len(a_i)
    dp = [[0 for i in range(0,m_i)] for j in range(0,n_i)]
    dp[0][0] = a_i[0]
    for i in range(1,n_i):
        dp[i][0] = dp[i-1][0] + a_i[i]
    for j in range(1,m_i):
        for i in range(0,n_i):
            minv = -1
            for k in range(0,i):
                temp = max(dp[i][0]-dp[k][0], dp[k][j-1])
                if minv == -1 or temp < minv:
                    minv = temp
            dp[i][j] = minv
    print(dp[n_i-1][m_i-1])

你可能感兴趣的:(三道头条的算法笔试题)