算法练习- 其他算法练习1

航天器

以一个数组中的任意两个元素计算面积,它们所在数组的索引的差值为宽度w,两值中的最小值为高度h,面积s = w*h。求数组元素可以组成的最大面积。

示例一
输入
10,9,8,7,6,5,4,3,2,1
输出
25

说明:
10和5之间宽度(索引差)为5,
高度取最小值也是5,面积为25
任意其他两元素所能获得的面积都小于25 所以最大面积为25

思路:

  • 所有元素降序排序
  • 索引差值从1开始,依次递增到最大;
  • 索引差值固定时,乘以最大的值时才可能得到最大的面积;
     

python代码:


def get_max_area(arr: list):
    if len(arr) < 2:
        return 0

    # 降序排列
    descend_list = sorted(arr, reverse=True)

    print("descend list:", descend_list)

    # 最大面积
    result = 0
    # 计算索引差值序列
    for i in range(1, len(arr)):
        temp = i * descend_list[i]
        if temp > result:
            result = temp

    return result


if __name__ == '__main__':
    import random
    arr = [random.randint(1, 20) for _ in range(10)]
    max_area = get_max_area(arr)
    print("max area:", max_area)

java代码

import java.util.Arrays;
import java.util.Scanner;

public class Main013 { // 公有类名 必须与类文件名相同
    public static void main(String[] args) {

        // 异常捕获
        try {
            // 输入
            Scanner scanner = new Scanner(System.in);
            String line = scanner.nextLine();

            solution(line);
        } catch(Exception e){
            System.out.println(e.getMessage());
        }

    }

    // 私有方法-供类内部 调用
    private static void solution(String line) {
        // 字符串分割  10,9,8,7,6,5,4,3,2,1
        String[] split = line.trim().split(",");
        // Arrays.stream 返回元素序列  映射为Long
        long[] longs = Arrays.stream(split)
                .mapToLong(Long::parseLong)
                .toArray();

        long res = 0;
        for (int i = 0; i < split.length; i++) {
            for (int j = i + 1; j < split.length; j++) {
                // Math 数学计算
                long area = Math.min(longs[i], longs[j]) * (j - i);
                res = Math.max(res, area);
            }
        }

        System.out.println(res);
    }
}

 

分糖果

输入num个糖果,每次取出一半分给同学们,当糖果不能平均分配(/2)时
可以从糖果盒中取出一个或放回一个糖果。
至少需要多少次能将手中糖果分至只剩一颗?
取出、放回算作一次;
平均分配算作一次;

示例一
输入
15
输出
5
说明
15+1=16
16/2=8
8/2=4
4/2=2
2/2=1

思路:

  • 至少多少次;
  • 不够平均分配时,应该++ 还是-- ?看对应操作后能否连除2
  • ( n u m + 1 ) / 2 % 2 = = 0 {(num+1) / 2 \% 2} == 0 (num+1)/2%2==0 时则++,否则–
    python代码
# __author__ = "laufing"


def dispatch_sweet(num):
    if num <= 0:
        return None

    elif num == 1:
        return 0

    times = 0
    while num > 1:
        if num % 2 == 0:
            num /= 2
            times += 1
        elif (num + 1) / 2 % 2 == 0:
            num += 1
            num /= 2
            times += 2
        else:
            num -= 1
            num /= 2
            times += 2

    return times


if __name__ == '__main__':
    print(dispatch_sweet(15))

java代码

import java.util.Scanner;


public class Main048 {
    public static void main(String[] args){

        try{
            Scanner scanner = new Scanner(System.in);
            String num_str = scanner.nextLine();
            long num = Integer.parseInt(num_str);

            solution(num);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }


    }

    private static void solution(long num){
        long times = 0;

        while(num != 1){
            if(num == 3){ // -1  /2   特殊处理
                times += 2; // 至少
                break;
            }

            if(num % 2 != 0 ){ // 无法平均分配时 该 ++ 还是该 -- ?
                if((num + 1) / 2 % 2 == 0){
                    num ++; // 取
                }else{
                    num --; // 放
                }
                times ++; // 取糖果 或者 放回糖果  算作一次
            }

            num = num / 2; // 平均分配   算作一次
            times ++;
        }

        System.out.println(times);
    }
}

 

卡片组成的最大数字

输入描述
正整数字符串,多个字符串以逗号分隔
输出描述
最大数字的字符串

示例一
输入
22,221
输出
22221

示例二
输入
4589,101,41425,9999
输出
9999458941425101

思路:

  • 比较两个整数字符串的大小;
  • 拼接在前面,形成的数值大,则认为该元素
  • 对所有数值字符串降序排序;最后拼接。
    python实现:
# __author__ = "laufing"


def comp_str(s1, s2):
    r1 = int(s1 + s2)
    r2 = int(s2 + s1)

    if r1 >= r2:
        return True
    else:
        return False


def bubble_sort(digit_list, comp_method=None):
    """
    :param digit_list: 待排序的列表
    :param comp_method: 比较大小的方法,默认为None
    :return: 排序的列表
    """
    n = len(digit_list)
    if n < 2:
    	return digit_list
    for i in range(n - 1):
        for j in range(n - 1 - i):
            if comp_method:
                if not comp_method(digit_list[j], digit_list[j + 1]):
                    digit_list[j], digit_list[j + 1] = digit_list[j + 1], digit_list[j]
            else:
                if digit_list[j] < digit_list[j+1]:
                    digit_list[j], digit_list[j + 1] = digit_list[j + 1], digit_list[j]

    return digit_list


def max_digit(digit_list):
    """
    :param digit_list: 数值字符串列表
    :return:
    """
    # 冒泡排序
    temp_list = bubble_sort(digit_list, comp_method=comp_str)
    return "".join(temp_list)


if __name__ == '__main__':
    # import random
    # alist = [random.randint(1, 10) for _ in range(10)]
    # print(bubble_sort(alist))
    while True:
        try:
            digit_list = input("输入:").strip().split(",")
            print("digit_list:", digit_list)

            print("max digit:", max_digit(digit_list))
        except KeyboardInterrupt:
            break

 
java实现

  • 有点问题
  • 22,2221
  • 2221,22
import java.util.Arrays;
import java.util.Scanner;


public class Main079 {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            String nums = scanner.nextLine();
            solution(nums);
        }
    }

    private static void solution(String nums) {
        StringBuilder builder = new StringBuilder();

        Arrays.stream(nums.split(","))
                .sorted((s1, s2) -> {
                    char[] v1 = s1.toCharArray();
                    char[] v2 = s2.toCharArray();
                    int len1 = v1.length;
                    int len2 = v2.length;

                    if (len1 == len2) {
                        return s2.compareTo(s1);
                    }

                    int min = Math.min(len1, len2);
                    for (int i = 0; i < min; i++) {
                        char c1 = v1[i];
                        char c2 = v2[i];
                        if (c1 != c2) {
                            return c2 - c1;
                        }
                    }

                    if (len1 > len2) {
                        return v1[0] - v1[min];
                    } else {
                        return v2[min] - v2[0];
                    }
                })
                .forEach(builder::append);

        System.out.print(builder);
    }
}

 

分苹果

按照A、B两种方案将所有的苹果划分为两堆;
A 按照二进制规则加和,按位加且不进位,分左右两份;
B 按照正常十进制加和,分左右两份。
依次划分,并分别按照方案A、B进行计算结果,在满足方案 A 等分两份时,B 划分的两份中的最大值?

第一行输入苹果数,
第二行输入每个苹果的重量
示例一
输入
3
3 5 6
输出
11

示例二
输入
8
7258 6579 2602 6716 3050 3564 5396 1773
输出
35165

思路:

  • 苹果重量排序;
  • 从第二个苹果开始,划分左边一份,右边一份;
  • 左边分别按照AB的方法求和;
  • 右边同样按照AB的方法求和;
  • 当按照A方法求和 两边相等时,取B 方法两份各自求和的最大值。

python实现

def get_b_max(m, alist):
    b_max = -1
    for i in range(1, m):
        # 分成左右两份后,分别按照A B规则 对两边求和
        a_left_sum = 0
        a_right_sum = 0
        b_left_sum = 0
        b_right_sum = 0
        # left 求和
        for j in range(i):
            # 左边 按照A规则求和
            a_left_sum ^= alist[j]
            # 左边按照B 规则求和
            b_left_sum += alist[j]

        # right 求和
        for j in range(i, m):
            a_right_sum ^= alist[j]
            b_right_sum += alist[j]

        # 满足A 均等分时
        if a_left_sum == a_right_sum:
            cur_max = max(b_left_sum, b_right_sum)
            b_max = max(cur_max, b_max)

    return b_max


if __name__ == '__main__':
    m = int(input().strip())
    alist = list(map(int, input().strip().split()))
    alist.sort()
    # 计算B获取的最大重量
    result = get_b_max(m, alist)
    print(result)



# 基于类实现
# __author__ = "laufing"
from functools import reduce


class DispatchApple:
    cur_max = 0
    def dispatch(self, num, weights):
        weights.sort()
        for i in range(1, num):
            # 划分两部分
            left = weights[:i]
            right = weights[i:]

            # 按照方案A、 B 对两边求和
            a_sum_left = reduce(self.bin_add, left)
            a_sum_right = reduce(self.bin_add, right)
            b_sum_left = reduce(self.decimal_add, left)
            b_sum_right = reduce(self.decimal_add, right)

            # A方案  计算结果为均等分
            if a_sum_left == a_sum_right:
                temp = max(b_sum_left, b_sum_right)
                # 多次取最大值
                self.cur_max = max(self.cur_max, temp)

    def bin_add(self, m: int, n: int):
        """
        :param m:  十进制数
        :param n:  十进制数
        :return:  二进制求和 ,不进位 (异或)
        """
        return m ^ n

    def decimal_add(self, m, n):
        return m + n


if __name__ == '__main__':
    dispatch = DispatchApple()
    while True:
        try:
            num = int(input("num:").strip())
            weights = list(map(int, input("weights:").strip().split()))

            print(num, weights)

            # 输出结果
            dispatch.dispatch(num, weights)
            print("max value:", dispatch.cur_max)
        except KeyboardInterrupt:
            break


java实现

import java.util.Arrays;
import java.util.Scanner;

public class Main086 {
    public static void main(String[] args) {

        try {
            Scanner scanner = new Scanner(System.in);
            int m = Integer.parseInt(scanner.nextLine());
            String weightString = scanner.nextLine();

            solution(weightString);
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
    }

    private static void solution(String line) {
        String[] strs = line.split(" ");
        int[] ints = new int[strs.length];
        // 转为整型
        for (int i = 0; i < strs.length; i++) {
            ints[i] = Integer.parseInt(strs[i]);
        }

        // 排序数组本身
        Arrays.sort(ints);
        // B最大重量
        int max = -1;
        for (int i = 1; i < ints.length - 1; i++) {
            int sumBin1 = 0;
            int sumBin2 = 0;
            int sum1 = 0;
            int sum2 = 0;
            //left
            for (int j = 0; j < i; j++) {
                sumBin1 = sumBin1 ^ ints[j];
                sum1 += ints[j];
            }
            //right
            for (int j = i; j < ints.length; j++) {
                sumBin2 = sumBin2 ^ ints[j];
                sum2 += ints[j];
            }

            if (sumBin1 == sumBin2) { // 满足A 均分两份
                max = Math.max(Math.max(sum1, sum2), max);
            }
        }

        System.out.println(max);
    }
}

 

敏感字段加密

  • 给定一个由多个命令字组成的命令字符串;

  • 字符串长度小于等于127字节,只包含大小写字母,数字,下划线和偶数个双引号,命令字之间以一个或多个下划线_进行分割

  • 可以通过两个双引号""来标识包含下划线_的命令字或空命令字(仅包含两个双引号),双引号不会在命令字内部出现

  • 对指定索引的敏感字段进行加密,替换为******(6个*),并删除命令字前后多余的下划线_。
    如果无法找到指定索引的命令字,输出字符串ERROR

输入描述
第一行为命令字索引 idx
第二行为命令字符串 cmd_string

输出描述
输出处理后的命令字符串
如果无法找到指定索引的命令字,输出字符串ERROR

示例一
输入
1
password__a12345678_timeout_100
输出
password_******_timeout_100

示例二
输入
2
aaa_password_“a12_45678”_timeout__100_“”_
输出
aaa_password_“******”_timeout_100_“”

思路:

  • 以_分割字符串;
  • 预处理 分割列表 并存入temp[ ],空字符直接删,空命令直接存起来,以单个双引号开头的要拼接,直到以单个双引号结束的命令,然后存起来;
  • 一般的命令字符串直接存起来;
  • 判断idx索引是否有效 0-n,有效则temp对应索引处的值用*替换(注意命令字含有双引号时要保留双引号)
  • 索引无效,输出ERROR字符串

python代码

def preprocess_list(alist):
    temp = []
    flag = False
    partial_cmd = ""
    for i in alist:
        if not i:
            continue
        elif i == '""':
            temp.append(i)
        elif i.startswith('"'):
            flag = True
            partial_cmd += i
        elif i.endswith('"'):
            flag = False
            partial_cmd += i
            temp.append(partial_cmd)
            partial_cmd = ""
        elif i:
            if flag:
                partial_cmd += i
            else:
                temp.append(i)

    return temp


if __name__ == '__main__':
    idx = int(input().strip())
    cmd_string = input().strip()

    cmd_list = cmd_string.split("_")
    # ['password', '', 'a12345678', 'timeout', '100']
    # ['aaa', 'password', '"a12', '45678"', 'timeout', '', '100', '""', '']
    print("current list:", cmd_list)

    cmd_list = preprocess_list(cmd_list)
    print("processed list:", cmd_list)

    # 指定索引处的 命令是否存在
    if idx >= 0 and idx < len(cmd_list):
        cur_cmd = cmd_list[idx]
        if cur_cmd.startswith('"') and cur_cmd.endswith('"'):
            cmd_list[idx] = '"' + '*'*6 + '"'
        else:
            cmd_list[idx] = '*'*6
        print("_".join(cmd_list))
    else:
        print("ERROR")



# 基于类,
# 以_原位 分片 整体字符串,注意开头和结尾的_
# flag表示 " 是否开始
# __author__ = "laufing"
class Encrypt:
    def solution(self, idx, cmd_str):
        # aaa__password_“a12_45678”_timeout__100_“”_
        # 分割命令字
        cmd_list = []
        n = len(cmd_str)

        # 起始位置
        start = 0
        while start < n - 1 and cmd_str[start] == "_":
            start += 1
        flag = False  # 控制引号 是否开始
        for i in range(n):
            # 分割
            if not flag and cmd_str[i] == "_" and i > start:
                cmd_list.append(cmd_str[start:i])

                start = i + 1
                while start < n - 1 and cmd_str[start] == "_":
                    start += 1

                if cmd_str[start] == '"':
                    flag = True

            if flag:
                if cmd_str[i] == '"' and i > start:
                    cmd_list.append(cmd_str[start:i+1])
                    flag = False
                    start = i + 1

                    while start < n - 1  and cmd_str[start] == "_":
                        start += 1
                    if cmd_str[start] == '"':
                        flag = True

        last_cmd = cmd_str[start:]
        if last_cmd != "_":
            cmd_list.append(last_cmd)
        # 分割出的命令
        print("cmd list:", cmd_list)

        # 加密
        try:
            cur_cmd = cmd_list[idx]
            if '"' in cur_cmd:
                cmd_list[idx] =  '"' + '*' * 6 + '"'
            else:
                cmd_list[idx] = '*' * 6
            print("_".join(cmd_list))
        except IndexError:
            print("ERROR")


if __name__ == '__main__':
    encry = Encrypt()

    while True:
        try:
            idx = int(input("idx:").strip())
            cmd_string = input("cmd:").strip()
            encry.solution(idx, cmd_string)

        except KeyboardInterrupt:
            break


java实现

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;


public class Main082 {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            int K = Integer.parseInt(scanner.nextLine());
            String S = scanner.nextLine();
            String res = solution(K, S);
            System.out.println(res);
        }
    }

    private static String solution(int k, String s) {
        List<String> commands = new LinkedList<>();


        char[] chars = s.toCharArray();
        for (int i = 0; i < s.length(); i++) {
            char cur = chars[i];
            String command = "";
            if (cur == '"') {
                int rPosQ = s.indexOf('"', i + 1);
                command = s.substring(i, rPosQ + 1);
                i = rPosQ + 1;
            } else {
                int pos_ = s.indexOf('_', i);
                if (pos_ != -1) {
                    command = s.substring(i, pos_);
                    i = pos_;
                } else {
                    command = s.substring(i);
                    i = s.length();
                }
            }
            if (!"".equals(command)) {
                commands.add(command);
            }
        }

        if (k < commands.size()) {
            commands.set(k, "******");
            StringBuilder builder = new StringBuilder();
            commands.forEach(x -> builder.append(x).append("_"));
            return builder.substring(0, builder.length() - 1);
        } else {
            return "ERROR";
        }
    }
}

 

最低位排序

  • 给定一个非空数组(列表),整数元素,
  • 按照元素十进制最低位从小到大进行排序,
  • 十进制最低位相同的元素,相对位置保持不变,
  • 当元素为负值时,十进制最低位等同于去除符号后对应十进制最低位。

输入描述:
给定一个非空数组(列表),其元素数据类型为32位有符号整数
数组长度为[1,1000]
输出描述:
输出排序后的数组

示例一
输入
1,2,5,-21,22,11,55,-101,42,8,7,32
输出
1,-21,11,-101,2,22,42,32,5,55,7,8

思路:

  • 定义比较两个数据的规则函数,以个位数比较大小;
  • 冒泡排序或者快速排序
    python实现
def comp_two_num(n1, n2):
    # 负数去符号
    n1 = abs(n1)
    n2 = abs(n2)

    n1_ = n1 % 10
    n2_ = n2 % 10

    return n1_ > n2_


if __name__ == '__main__':
    alist = list(map(int, input().strip().split(",")))
    n = len(alist)
    for i in range(n-1):
        for j in range(n-1-i): # 冒出最大值        # for j in range(i+1, n) 冒出最小值
            if comp_two_num(alist[j], alist[j+1]):
                alist[j], alist[j+1] = alist[j+1], alist[j]

    print(alist)
    str_alist = list(map(str, alist))
    print(",".join(str_alist))

java实现

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;


public class Main0025 {

  public static final String COMMA = ",";

  public static void main(String[] args) {

    try (Scanner scanner = new Scanner(System.in)) {
      String line = scanner.nextLine();
      solution(line);
    }
  }

  private static void solution(String line) {
    String[] nums = line.split(COMMA);
    List<Integer> list = new ArrayList<>();
    for (String num : nums) {
      list.add(Integer.parseInt(num));
    }
    list.sort(new Comparator<Integer>() {
      @Override
      public int compare(Integer o1, Integer o2) {
        return getKey(o1) - getKey(o2);
      }

      public Integer getKey(int i) {
        i = i > 0 ? i : -i;
        return i % 10;
      }
    });

    for (int i = 0; i < list.size(); i++) {
      System.out.print(list.get(i));
      if (i != list.size() - 1) {
        System.out.print(COMMA);
      }
    }
  }
}

 

选座位

  • 座位有一排共n个座位,编号分别为[0…n-1];
  • 员工一个接着一个进入会议室,并且任何时候可以离开;
  • 一个员工进入时,要坐到最大社交距离的座位

例如:
位置A与左右有员工落座的位置距离分别为3和2
位置B与左右有员工落座的位置距离分别为2和3
则认为A、B是等效的座位,影响因素取最小的距离(即为当前座位的最大的社交距离)。
如果有多个这样的座位,则坐到索引最小的那个座位

输入:
第一行 座位数n;
第二行 进出场状态,1进场,-4表示座位4的人离场,0座位的人不离开。

输出:
最后进来的员工,坐在第几个位置?
如果位置已满 则输出-1

示例一
输入
10
[1,1,1,1,-4,1] 最后一个1表示最后进来的人
输出
5

说明
第一个入场的人坐在任何位置都行,但要索引最小的位置,即座位0;
第二个入场的人坐在位置9,与第一个人距离最远;
第三个人可以坐在位置4或者5,因为4与5是等效的座位,取索引最小,故4;

第四个人选择座位2
位置2与0和4的距离位置为(2和2)
位置6与4和9的距离位置为(2和3)
位置7与4和9的距离位置为(3和2)
影响因素都为两个位置,按照要求需索引最小的座位
所以座位2

4号座位员工离开

最后进来的员工最后坐在5号座位

思路:

  1. 使用数组表示每个座位是否有人,有人存储1,否则存储0;
  2. 每次进入一个人,都判断是否满座,若满坐则输出-1,否则进入选座的流程;
  3. 第一个进入的人,坐在索引为0的位置,对应存入1;后续进入的人依次从索引为1-> n -1的所有座位中选择最大社交距离的位置; 若有离场的,则对应座位存入0;
  4. 定义一个座位类,并且多个座位类之间(按自身的社交距离)可以相互比较大小;

python实现

# __author__ = "laufing"

# 1
# [1, 1]  -1

# 10
# [1,1,1,1,-4,1]  5

# 15
# [1, 1, 1, 1, -3, 1]    3
class SelectSeat:
    def __init__(self):
        self.seat_num = 0
        self.seat_status = None
        # 入场一个人的候选座位,要选择最大社交距离
        self.cadidate_seat = []

    def solution(self, n, enter_series):
        self.seat_num = n
        # 座位的初始状态
        self.seats = [0] * n
		
		min_idx = float("inf")
        # 遍历入场序列
        for v in enter_series:
            if v == 1: # 表示入场
                # 判满
                if self.is_full():
                    print(-1)
                    return
                # 未满 ,则正常入场
                if self.seats[0] == 0: # 第一个入场的人 坐在index=0处
                    self.seats[0] = 1
                    print(f"cur {v}-入座0")
                    continue
                else:
                    # 从 1 -> n - 1 的座位中选择最大社交距离的位置
                    for cur in range(1, n):
                        if self.seats[cur] == 1:  # 已经被坐,则跳过
                            continue
                        left = cur - 1
                        right = cur + 1
                        while left >=0 and self.seats[left] == 0:
                            left -= 1

                        while right < n and self.seats[right] == 0:
                            right += 1
                        if right == n:
                            right = float("inf")  # 正无穷
                        # 存储当前候选座位
                        self.cadidate_seat.append(Seat(left, cur, right))

                    # 确定最大社交距离的座位
                    temp_list = sorted(self.cadidate_seat, key=lambda i:i.social_dist, reverse=True)
                    min_idx = temp_list[0].cur_seat
                    for j in range(1, len(temp_list)):
                        if temp_list[j].social_dist == temp_list[0].social_dist:
                            min_idx = min(min_idx, temp_list[j].cur_seat)
                        else:
                            break
                    print(f"cur {v}-入座{min_idx}")
                    self.seats[min_idx] = 1
                    # 清空候选
                    self.cadidate_seat.clear()
            else: # 出场
                self.seats[abs(v)] = 0
        print("最后入座:", min_idx)

    def is_full(self):
        """
            会场是否满
        :return:
        """
        return sum(self.seats) == self.seat_num


class Seat:
    """
        座位类, 每个座位对象都有自己的社交距离
    """
    def __init__(self, left, cur, right):
    	# 当前座位
        self.cur_seat = cur
        self.social_dist = min(cur - left, right - cur)


if __name__ == '__main__':
    # print(2 ** 1024 < float("-inf"))

    select_seat = SelectSeat()
    while True:
        try:
            n = int(input("n:").strip())
            enter_series = eval(input("in_out:").strip())

            print("origin:", enter_series)

            # 输出最后一个入场的人 坐的位置
            select_seat.solution(n, enter_series)
        except KeyboardInterrupt:
            break


java

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;


public class Main0113 {
  public static void main(String[] args) {
    try (Scanner scanner = new Scanner(System.in)) {
      int n = Integer.parseInt(scanner.nextLine());
      String seatOrLeave = scanner.nextLine();

      String[] split = seatOrLeave
          .substring(1, seatOrLeave.length() - 1)
          .split(",");

      int[] sol = new int[split.length];
      for (int i = 0; i < split.length; i++) {
        sol[i] = Integer.parseInt(split[i]);
      }

      int[] seats = new int[n];

      int res = 0;
      for (int action : sol) {
        if (checkFull(seats, action)) {
          System.out.println(-1);
          return;
        }
        res = solution(seats, action);
      }
      System.out.print(res);
    }
  }

  private static boolean checkFull(int[] seats, int action) {
    if (action == 1) {
      int sum = 0;
      for (int seat : seats) {
        sum += seat;
      }
      return sum == seats.length;
    }
    return false;
  }

  private static int solution(int[] seats, int action) {
    if (action == 1) {
      //位置零
      if (seats[0] == 0) {
        seats[0] = 1;
        return 0;
      } else {
        List<Seat> list = new LinkedList<>();
        for (int i = 1; i < seats.length; i++) {
          if (seats[i] != 1) {
            int l = i - 1, r = i + 1;
            while (l >= 0 && seats[l] != 1) l--;
            while (r < seats.length && seats[r] != 1) r++;
            if (r == seats.length) r = Integer.MAX_VALUE;
            list.add(new Seat(i, i - l, r - i));
          }
        }
        list.sort(Seat::compareTo);
        int n = list.get(0).n;
        seats[n] = 1;
        return n;
      }
    } else {
      //离开
      seats[Math.abs(action)] = 0;
      return -4;
    }
  }

  static class Seat implements Comparable<Seat> {
    public int n;
    public int l;
    public int r;

    public Seat(int n, int l, int r) {
      this.n = n;
      this.l = l;
      this.r = r;
    }

    @Override
    public int compareTo(Seat o) {
      // 左右最小值
      int min1 = Math.min(this.l, this.r);
      int min2 = Math.min(o.l, o.r);
      if (min1 != min2) {
        return min2 - min1;
      } else {
        return this.n - o.n;
      }
    }
  }
}

 

路灯照明

路灯照明
题目描述
在一条笔直的公路上安装了N个路灯,
从位置0开始安装,路灯之间间距固定为100米
每个路灯都有自己的照明半径
请计算第一个路灯和最后一个路灯之间,
无法照明的区间的长度和。

输入描述
第一行为一个数N,表示路灯个数,1 <= N <= 100000
第二行为N个 以空格分割的数,依次表示路灯的照明半径,1 <= 照明半径

输出描述
无法照明的区间的长度和。

示例一
输入
2
50 50
输出
0
说明
路灯1覆盖0-50 ; 路灯二覆盖50-100
路灯1和路灯2 之间(0-100米)无未覆盖的区间

 
思路:

  • 数组存储路灯半径,从第二个半径开始遍历,依次计算与前一个路灯半径的黑暗区域;
  • 若黑暗区域>0, 则累加;

python:


class CalcShadow:
    def solution(self, n, radius_list):
        result = 0
        for i in range(1, n):
            temp = 100 - (radius_list[i] + radius_list[i-1])
            if temp > 0 :
                result += temp
        print(result)
        return result


if __name__ == '__main__':
    calc_shadow = CalcShadow()
    while True:
        try:
            n = int(input("n:").strip())
            radius_list = list(map(int, input("radius:").strip().split()))
            calc_shadow.solution(n, radius_list)
        except KeyboardInterrupt:
            break

java:

import java.util.Scanner;


public class Main0093 {
  public static void main(String[] args) {
    try (Scanner scanner = new Scanner(System.in)) {
      int n = scanner.nextInt();
      int[] ints = new int[n];
      for (int i = 0; i < n; i++) {
        ints[i] = scanner.nextInt();
      }
      solution(ints);
    }
  }

  private static void solution(int[] ints) {

    byte[] bytes = new byte[(ints.length - 1) * 100];

    for (int i = 0; i < ints.length; i++) {
      int pos = i * 100;
      int left = Math.max(pos - ints[i], 0);
      int right = Math.min(pos + ints[i], bytes.length);

      for (int k = left; k < right; k++) {
        bytes[k] = 1;
      }
    }

    int count = 0;
    for (byte b : bytes) {
      if (b == 0) count++;
    }
    System.out.println(count);

  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值