算法练习- 其他算法练习6

数字序列比大小

  • A、B两人一人一个整数数组,长度相等,元素随即;
  • 两人随便拿出一个元素(弹出),比较大小,赢的得一分,输的减去一分,否则分值都不变;
  • B每取一个元素都明示,求A赢B时的最大分值;

输入:
n 数组长度
arr1
arr2
输出:
求A赢B时的最大分值

示例1
输入:
3
4 8 10
3 6 4
输出:
3

示例2
输入:
4
3 6 2 10
2 5 7 11
输出:
3

思路:

  • 对两个数组排序,并使用一个flag表示A 有能赢B 的元素;
  • arr_b弹出第一个值,arr_a中取能赢arr_b的最小值;
  • score_a 累加1;
  • 示例可以找arr_a排序后元素全小于arr_b;全大于arr_b;有大于有小于arr_b;

python:

n = int(input().strip())
arr_a = list(map(int, input().strip().split()))
arr_b = list(map(int, input().strip().split()))
arr_a.sort()
arr_b.sort()

score_a = score_b = 0

flag = True # 表示A能赢B
while flag and arr_b:
    flag = False
    e_b = arr_b.pop(0)
    i = 0

    # 取保证A赢的最小元素
    while i < len(arr_a) and arr_a[i] <= e_b: # 只有大于才算赢
        i += 1

    if i < len(arr_a):
        flag = True
        arr_a.pop(i)
        score_a += 1
        score_b -= 1


print(score_a)

最佳植树距离

  • 给定一些适合种树的坐标点和树苗数量;
  • 让树苗均匀分开,确定最佳的种树距离;

示例1
输入:
7 坐标的数量
1 5 3 6 10 7 13 坐标
3 树苗数量
输出:
6 最佳的植树距离

思路:

  • coords坐标数组升序排序;
  • 植树距离最小为1,最大max_dist为【最大坐标-最小坐标】;
  • for dist in range(1, max_dist+1);
    • for i in range(coords[0], coords[-1]+1, dist):
    • used_trees += 1 并且保存植树的坐标位置
  • used_tree > has_tree continue;
  • used_tree == has_tree 判断是否合法坐标;
  • used_tree < has_tree 距离太大 break

python:


coord_n = int(input().strip())
coords = list(map(int, input().strip().split()))
coords.sort()
trees_m = int(input().strip())

find_best_dist = False

max_dist = coords[-1] - coords[0]
dist = 1
for dist in range(1, max_dist+1):
    used_trees = 0
    pos_list = []
    for i in range(coords[0], coords[-1] + 1, dist):
        used_trees += 1
        pos_list.append(i)
    if used_trees > trees_m: # 说明当前间距太小
        continue

    elif used_trees == trees_m:
        # 如果当前位置都是有效位置,且以均匀种植完所有的树苗,则break
        if all([True if i in coords else False for i in pos_list]):
            find_best_dist = True
            break
    else:
        break

if find_best_dist:
    print(dist)
else:
    print(-1)

文艺汇演

  • 一个人只能观看一场演出,不能迟到、早退;
  • 连续观看的演出至少有15分钟的间隔;
  • 根据时间表,计算最多可以看几场演出;

示例1
输入:
2 演出场数
720 120 开始时间-持续时间
840 120 开始时间-持续时间
输出:
1

示例2
输入:
5
20 120
80 120
130 70
140 60
200 50
输出:
2

示例3
输入:
4
20 200
30 30
50 45
110 60
输出:
2

思路:

  • 动态规划
  • 所有场次按照开始时间升序排序
  • 后一场的开始时间与前一场的结束时间比较,是否有15分钟的间隔;
    • 有则可以看,取后面这一场的结束时间,作为后续比较;
    • 间隔不足,则选择看结束时间最早的那一场,刷新结束时间;

python:


def calc_max_plays(arr):
    global n, can_see_num
    if n == 1: # 场次是>=1
        return
    # 结束时间
    end_time = arr[0][0] + arr[0][1]
    cur = 1
    while cur < n:
        if arr[cur][0] - end_time >= 15:
            # 可以看 则刷新结束时间
            can_see_num += 1
            end_time = arr[cur][0] + arr[cur][1]
        else:
            # 选择场次(最早结束的场次)
            end_time = min(end_time, arr[cur][0] + arr[cur][1])

        cur += 1
	return

if __name__ == '__main__':
    # 所有场次数
    n = int(input().strip())
    plays = []
    for i in range(n):
        start_last = list(map(int, input().strip().split()))
        plays.append(start_last)
    # 按照开始时间排序
    plays = sorted(plays, key=lambda i:i[0])
    print(plays)

    can_see_num = 1
    # 计算最多场次
    calc_max_plays(plays)

    print(can_see_num)


计算误码率

  • 误码率 = 错误比特数 / 总比特数;以字符串表示总位数,错误字符数,即为错误比特数;
  • 字符串会被压缩,如2A3B4D5X 表示“AABBBDDDDXXXXX”;
  • 第一次输入原始的压缩字符串,第二次输入出错的压缩字符串;
  • 解压后两个字符串长度相等,计算误码率;

示例1
输入:
3A3B
2A4B
输出:
1/6

示例2
输入:
5Y5Z
5Y5Z
输出:
0/10

示例3
输入:
4Y5Z
9Y
输出:
5/9

思路:

  • 还原字符串,并逐一对比,统计所有字符个数和错误字符个数;
  • 输出误码率比例;

python:


s1 = "5Y5Z"
s2 = "5Y5Z"

s1_restore = ""
s2_restore = ""

s1_char_num = 0
for i in s1:
    if i.isdigit():
        s1_char_num = int(i)
    else:
        s1_restore += i * s1_char_num

s2_char_num = 0
for i in s2:
    if i.isdigit():
        s2_char_num = int(i)
    else:
        s2_restore += i * s2_char_num

# 两者恢复后长度相等
n = len(s1_restore)
error_num = 0
for i in range(n):
    if s1_restore[i] != s2_restore[i]:
        error_num += 1

print(f"{
      
      error_num}/{
      
      n}")

二维伞的雨滴效应

  • 输入一个正整数数组,无0,无重复,数组最小长度为1;
  • 判断是否为二叉排序树,是则输出1,并输出左右子树的叶子节点值;
  • 不是二叉排序树,则输出0 0 0,中间空格分隔;

示例:
输入:
8 3 1 6 4 7 10 14 13
输出:
1 1 13

思路:

  • 构造二叉搜索树,前序遍历结果与数组对比,一致则数组为二叉搜索树的前序遍历结果;
  • 前序遍历,最后一个数是最右侧叶子节点;
  • 中序遍历,第一个节点为最左侧叶子节点;

python:



class TreeNode(object):
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right


# 构造二叉排序树
def insert_node(root, val):
    if root is None:
        return TreeNode(val)

    if val > root.data:
        # 右边插入
        root.right = insert_node(root.right, val)
    else:
        root.left = insert_node(root.left, val)

    return root


# 中序遍历
# 左子树、root、右子树

if __name__ == '__main__':

    # 构造二叉树排序树
    alist = [8, 3, 1, 6, 4, 7, 10, 14, 13]
    root = None
    for i in alist:
        root = insert_node(root, i)
    root2 = root

    in_order_list = []
    # 中序遍历
    stack = []
    while root or stack:
        while root:
            in_order_list.append(root.data)
            # 根节点入栈
            stack.append(root)
            root = root.left

        root = stack.pop()
        root = root.right

    output_list = []
    if alist == in_order_list:
        output_list.append(1)
        # 中序遍历  获取最左侧的叶子节点
        pre = None
        while root2:
            pre = root2
            root2 = root2.left
        output_list.append(pre.data if pre.right is None else 0)
        # 前序获取最右边叶子节点
        output_list.append(in_order_list[-1])

    else:
        output_list = [0, 0, 0]

    print(output_list)

阿里巴巴找黄金宝箱4

  • 有0-N个箱子排成一个环,每个箱子有自己对应的编号;
  • 输出每一个箱子后第一个比自己编号大的数;
  • 多个数以,分隔输出;

示例1:
输入:
2,5,2
输出
5,-1,5

示例2:
输入:
3,4,5,6,3
输出
4,5,6,-1,4

思路:

  • 数组复制一份,拼接在一起;
  • 单调栈,从栈顶到栈底,递增为单调递增栈;否则为单调递减栈;
  • 单调栈解决大小关系;这里用于存储arr的索引

python:


if __name__ == '__main__':
    arr1 = list(map(int, "3,4,5,6,3".split(",")))
    n = len(arr1)
    # 存储比0-n对应位置大的第一个数
    arr2 = [-1 for i in range(n)]

    # 单调栈
    stack = []
    # 双份数组
    double_arr = arr1 + arr1
    for i in range(2*n):
        cur_data = double_arr[i]
        while stack and cur_data > arr1[stack[-1]]:
            # 找到当前比idx处大的第一个数
            cur_idx = stack.pop()
            arr2[cur_idx] = cur_data
        if i < n:
            # 索引入栈
            stack.append(i)
    arr2_str = map(str, arr2)
    print(",".join(arr2_str))

java

import java.util.Scanner;
import java.util.*;
import java.lang.Integer;


public class Main{
    
    

    public static void main(String[] args) {
    
    

        Scanner sc = new Scanner(System.in);

        int[] nums = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();

        int len = nums.length;
        //将数组复制成双份数组([1,2,3] -> [1,2,3,1,2,3])
        int[] doubleNums = Arrays.copyOf( nums, len *2);
        System.arraycopy( nums, 0, doubleNums, len, len);
        //各位置对应第一个比他大的数
        int[] resInts = new int[len];
        //初始化为 -100001,因为宝箱数值范围 >= -100000,<=100000
        Arrays.fill( resInts, -100001);

        Deque<Integer> deque = new ArrayDeque<>();
        for(int i=0; i<len*2; i++){
    
    

            int num = doubleNums[i];
            System.out.println("55--" + num);
            //单调栈
            while (!deque.isEmpty() && num > nums[deque.peek()]){
    
     // deque.peek() 访问栈顶
                //双向队列中有值,且最后一个值小于当前数字则取出
                //并通过队列中的索引,对 resInts 进行赋值
                System.out.println("出队" + num);
                int index = deque.pop(); // 弹出栈顶

                resInts[index] = num;
            }

            if(i < len){
    
    
                System.out.println("入队" + i);
                deque.push(i);
            }
        }

        String res = "";
        for(int i : resInts){
    
    
            if(i == -100001){
    
    
                //等于 -100001 说明不存在,则输出 -1
                i = -1;
            }
            res += i + ",";
        }

        System.out.println(res.substring( 0, res.length() - 1));
    }

}

&nbsp;

树状结构查询

  • 输入节点组合的行数n;
  • n行中每行是(子节点 父节点)的组合;
  • 最后一行输出 要查询的节点;
  • 输出该查询节点的所有子节点;

示例
输入:
5
b a
c a
d c
e c
f d
c
输出:
d
e
f

思路:

  • 哈希存储根节点、子树的根节点;
  • 广度搜索 + 递归;

python实现:


def output_ch(node):
    global root_dict, result_nodes
    chs = root_dict.get(node)
    if chs is None:
        return
    result_nodes += chs
    for node in chs:
        output_ch(node)

if __name__ == '__main__':
    n = int(input())
    root_dict = {
    
    }
    for i in range(n):
        ch, root = input().strip().split()
        if root in root_dict:
            root_dict[root].append(ch)
        else:
            root_dict[root] = [ch]

    # 要查询的节点
    target_ch = input().strip()
    # 输出查询节点的所有子节点
    result_nodes = []
    output_ch(target_ch)

    # 字典序排序
    result_nodes.sort()
    for i in result_nodes:
        print(i)

人气最高的店铺

  • 输入n个市民,m个店铺,每个市民只能为一个店铺投1票;
  • 1号店铺发放q元的金额补贴,可以让某市民为其投1票;
  • 计算1号店铺至少发放多少补贴,才可以人气最高。

示例1
输入:
5,5 市民数和店铺数
2,10 投票意向(1-m)改投1号店需要的补贴金额
3,20
4,30
5,40
5,90
输出:
50

思路:

  • 每组投票及补贴,按照需要的补贴金额从小到大排序;
  • 统计每个商铺的票数;
  • get_vote()函数,如果当前排名1店铺人气最高,则return min_cost;
    -否则,从补贴成本最小的票中拉一票;更新相应商铺的票数,再递归调用get_vote()
  • 待优化

python:


# 5,5
# 2,10
# 3,20
# 4,30
# 5,40
# 5,90


def get_vote(shop_votes, votes_list):
    global min_cost
    # 当前人气排名
    current_rand = sorted(shop_votes.items(), key=lambda i:i[1], reverse=True)
    if current_rand[0][0] == 1 and current_rand[0][1] > current_rand[1][1]:
        return min_cost

    temp_vote = votes_list.pop(0)
    cur_shope = temp_vote[0]
    shop_votes[cur_shope] -= 1
    # 票数 +1
    shop_votes[1] += 1
    # 成本 +q
    min_cost += temp_vote[1]

    return get_vote(shop_votes, votes_list)


if __name__ == '__main__':
    n, m = list(map(int, input().split(",")))
    votes = []
    shop_votes = {
    
    }
    for i in range(n):
        temp = list(map(int, input().strip().split(",")))
        if temp[0] in shop_votes:
            shop_votes[temp[0]] += 1
        else:
            shop_votes[temp[0]] = 1
        votes.append(temp)

    votes = sorted(votes, key=lambda i:i[1])

    if 1 not in shop_votes:
        shop_votes[1] = 0

    min_cost = 0

    origin_votes_list = votes.copy()
    get_vote(shop_votes, origin_votes_list)

    print(min_cost)

采样过滤

pass
 

最节约的备份方法

pass

猜你喜欢

转载自blog.csdn.net/weixin_45228198/article/details/132509322