#P3005. 计算最接近的数(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 320
            Accepted: 81
            Difficulty: 3
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>模拟          
 
计算最接近的数(100分)
题面描述
给定一个数组 X 和正整数 K,请找出使表达式:
X[i]−X[i+1]−⋯−X[i+K−1]结果最接近于数组中位数的下标 i。如果有多个 i 满足条件,请返回最大的 i。
数组中位数的定义为:对于长度为 N 的数组,按照元素值大小升序排列后,下标为 ⌊N/2⌋ 的元素的值。
思路
首先,通过对数组 X 进行排序来确定其中位数。然后,遍历所有可能的起始下标 i,计算表达式 X[i]−X[i+1]−⋯−X[i+K−1] 的值,并与中位数求绝对差。过程中记录最小的差值及对应的下标,如果出现相同的最小差值,则选择较大的下标 i。最终返回使表达式结果最接近中位数的最大下标。
cpp
#include <bits/stdc++.h>
using namespace std;
// 函数:查找最接近中位数的下标
int findClosestIndex(vector<int> X, int K) {
    int n = X.size();
    // 复制并排序数组以找到中位数
    vector<int> sortedX = X;
    sort(sortedX.begin(), sortedX.end());
    int median = sortedX[n / 2];
    
    int closestIndex = -1;
    long long minDiff = LLONG_MAX;
    
    // 遍历所有可能的i
    for(int i = 0; i <= n - K; ++i){
        // 计算表达式值:X[i] - X[i+1] - ... - X[i+K-1]
        long long expr = X[i];
        for(int j = 1; j < K; ++j){
            expr -= X[i + j];
        }
        // 计算与中位数的绝对差
        long long diff = abs((long long)expr - (long long)median);
        // 更新最小差值和对应的下标
        if(diff < minDiff || (diff == minDiff && i > closestIndex)){
            minDiff = diff;
            closestIndex = i;
        }
    }
    
    return closestIndex;
}
int main(){
    string input;
    // 读取整行输入
    getline(cin, input);
    
    // 查找数组部分和K的分隔位置
    size_t commaPos = input.find_last_of(',');
    
    
    // 提取数组字符串
    string arrayStr = input.substr(0, commaPos);
    // 提取K
    string KStr = input.substr(commaPos + 1);
    
    // 去除数组字符串中的方括号
    arrayStr.erase(remove(arrayStr.begin(), arrayStr.end(), '['), arrayStr.end());
    arrayStr.erase(remove(arrayStr.begin(), arrayStr.end(), ']'), arrayStr.end());
    
    // 分割数组字符串为数字
    vector<int> X;
    string num = "";
    for(char c : arrayStr){
        if(c == ','){
            if(!num.empty()){
                X.push_back(stoi(num));
                num = "";
            }
        }
        else if(isdigit(c)){
            num += c;
        }
    }
    if(!num.empty()){
        X.push_back(stoi(num));
    }
    
    // 转换K为整数
    int K = stoi(KStr);
    
    // 调用函数并输出结果
    cout << findClosestIndex(X, K) << endl;
    
    return 0;
}
python
def find_closest_index(X, K):
    n = len(X)
    # 复制并排序数组以找到中位数
    sorted_X = sorted(X)
    median = sorted_X[n // 2]
    closest_index = -1
    min_diff = float('inf')
    # 遍历所有可能的i
    for i in range(n - K + 1):
        # 计算表达式值:X[i] - X[i+1] - ... - X[i+K-1]
        expr = X[i]
        for j in range(1, K):
            expr -= X[i + j]
        # 计算与中位数的绝对差
        diff = abs(expr - median)
        # 更新最小差值和对应的下标
        if diff < min_diff or (diff == min_diff and i > closest_index):
            min_diff = diff
            closest_index = i
    return closest_index
if __name__ == "__main__":
    import sys
    # 读取整行输入
    input_line = sys.stdin.readline().strip()
    # 查找数组部分和K的分隔位置
    comma_pos = input_line.rfind(',')
   
    # 提取数组字符串
    array_str = input_line[:comma_pos]
    # 提取K
    K_str = input_line[comma_pos + 1:]
    # 去除数组字符串中的方括号
    array_str = array_str.replace('[', '').replace(']', '')
    # 分割数组字符串为数字
    X = list(map(int, array_str.split(',')))
    # 转换K为整数
    K = int(K_str)
    # 调用函数并输出结果
    print(find_closest_index(X, K))
java
import java.util.*;
public class ClosestIndexFinder {
    // 函数:查找最接近中位数的下标
    public static int findClosestIndex(int[] X, int K) {
        int n = X.length;
        // 复制并排序数组以找到中位数
        int[] sortedX = X.clone();
        Arrays.sort(sortedX);
        int median = sortedX[n / 2];
        
        int closestIndex = -1;
        long minDiff = Long.MAX_VALUE;
        
        // 遍历所有可能的i
        for(int i = 0; i <= n - K; i++){
            // 计算表达式值:X[i] - X[i+1] - ... - X[i+K-1]
            long expr = X[i];
            for(int j = 1; j < K; j++){
                expr -= X[i + j];
            }
            // 计算与中位数的绝对差
            long diff = Math.abs(expr - (long)median);
            // 更新最小差值和对应的下标
            if(diff < minDiff || (diff == minDiff && i > closestIndex)){
                minDiff = diff;
                closestIndex = i;
            }
        }
        
        return closestIndex;
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        // 读取整行输入
        String input = sc.nextLine().trim();
        
        // 查找数组部分和K的分隔位置
        int commaPos = input.lastIndexOf(',');
        // 提取数组字符串
        String arrayStr = input.substring(0, commaPos);
        // 提取K
        String KStr = input.substring(commaPos + 1);
        
        // 去除数组字符串中的方括号
        arrayStr = arrayStr.replace("[", "").replace("]", "");
        
        // 分割数组字符串为数字
        String[] numStrs = arrayStr.split(",");
        int[] X = new int[numStrs.length];
        for(int i = 0; i < numStrs.length; i++){
            X[i] = Integer.parseInt(numStrs[i].trim());
        }
        
        // 转换K为整数
        int K = Integer.parseInt(KStr.trim());
        
        // 调用函数并输出结果
        System.out.println(findClosestIndex(X, K));
    }
}
        题目描述
给定一个数组X和正整数K,请找出使表达式:
X[i]−X[i+1]−...−X[i+K−1]
结果最接近于数组中位数的下标 i ,如果有多个 i 满足条件,请返回最大的 i.
其中,数组中位数:长度为 N 的数组,按照元素的值大小升序排列后,下标为 N/2 元素的值
备注
数组 X 的元素均为正整数
X 的长度 n 取值范围:2≤n≤1000
K 大于 0 目小于数组的大小
i 的取值范围: 0≤i<1000
题目的排序数组 X[N]的中位数是 X[N/2]
样例1
输入
[50,50,2,3],2
输出
1
说明
中位数为 50 :[50,50,2,3] 升序排序后变成 [2,3,50,50] ,中位数为下标 4/2=2 的元素 50
计算结果为 1 :X[50,50,2,3] 根据题目计算 X[i]−...−X[i+k−1]
得出三个数 0(X[0]−X[1]=50−50) 、48(X[1]−X[2]=50−2) 和 −1(X[2]−X[3]=2−3) ,
其中 48 最接近 50 ,因此返回下标 1 。