Huawei OD computer-based test algorithm questions: birthday gift

Question part

topic birthday present
difficulty easy
Question description Maverick's child's birthday is coming soon. He plans to buy a cake and a small gift for his child. One cake and one small gift each. His budget does not exceed x yuan. Cakes and small gifts are available in a variety of price ranges.
Enter description The first line indicates the unit price of cake, separated by commas.
The second line represents the unit price of the gift, separated by commas.
The third line represents the x budget.
Output description The output number represents the total number of purchase options.
Additional information 1 ≤ cake.length ≤ 10^{5}
1 ≤ gift.length ≤10^{5}
1 ≤ cake[], gift[] ≤ 10^{5}
1 ≤ X ≤2 * 10^{5}
------------------------------------------------------
Example
Example 1
enter 10,20,5
5,5,2
15
output 6
illustrate Mavericks has 6 purchase plans. The corresponding subscripts of the selected cake and the selected gift in the array are:
The first plan: cake[0]+ gift [0] = 10 + 5 = 15;
The second option: cake[0]+ gift[1] = 10 + 5 = 15;
The second option 3 options: cake[0]+ gift[2] = 10 + 2 = 12;
4th option: cake[2]+ gift[0] = 5 + 5 = 10;
The 5th option: cake[2]+ gift[1] = 5 + 5 = 10;
The 6th option: cake[2]+ gift [2] = 5 + 2 = 7.


Interpretation and analysis

Item explanation

Given 2 sets of data, pick 1 from each set of data so that the sum of the 2 numbers is not higher than the specified value x.

Analysis Yoshiro

If you traverse each combination of the two sets of numbers one by one, the time complexity is O(n^{2}). Since the maximum length of cake and gift is 10^{5}, when their length is large, the performance will become very poor. We have a better method.

The implementation is as follows:
1. Sort cakes and gifts from large to small.
2. Perform a binary search on cake, find the subscript corresponding to the maximum value less than x from cake, and set it as minCake. At this time, the calculated subscript range of cakes that may be bought in cake is [minCake, cake.length - 1]. For cake traversal within the subscript range (assuming that the subscript currently being traversed is i), perform step 3.
3. As in step 2, assuming that the current cake is cake[i], then the maximum price of the gift that can be purchased is x - cake[i], which is set to giftMaxValue. Use binary search to find the maximum value whose price is not higher than giftMaxValue. Let the subscript be j, then the optional range of subscripts for gift is [j, gift.length -1]. This means that when cake[i] is selected, the number of gifts available is gift.length - j.
4. Continue to traverse the next cake, that is, the next i, as in step 3, recalculate the giftMaxValue. The giftMaxValue at this time must be greater than the previously calculated giftMaxValue, which means that this round The range of j in the gift subscript must be between 0 and j calculated in the previous round. Perform a binary search on [0, j calculated in the previous round] to find the maximum value (that is, the lowest subscript) that is not greater than giftMaxValue. , that is, calculate the number of optional gifts when selecting the current cake.
5. Continue to step 4 until all cakes have been traversed. The sum of all available options is the total number of purchase plans.

The time complexity of this solution is O(nlogn) and the space complexity is O(n).


Code

Java code

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

/**
 * 生日礼物
 * 
 * @since 2023.10.31
 * @version 0.1
 * @author Frank
 *
 */
public class BirthdayGift {

    public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	while (sc.hasNext()) {
	    String input = sc.nextLine();
	    String[] strNumber = input.split(",");
	    Integer[] cakes = new Integer[strNumber.length];
	    for (int i = 0; i < strNumber.length; i++) {
		cakes[i] = Integer.parseInt(strNumber[i]);
	    }

	    input = sc.nextLine();
	    strNumber = input.split(",");
	    Integer[] gifts = new Integer[strNumber.length];
	    for (int i = 0; i < strNumber.length; i++) {
		gifts[i] = Integer.parseInt(strNumber[i]);
	    }

	    input = sc.nextLine();
	    int x = Integer.parseInt(input);
	    processBirthdayGift(cakes, gifts, x);
	}
    }

    private static void processBirthdayGift(Integer[] cakes, Integer[] gifts, int x) {	
	// 从大到小排序
	Comparator<Integer> comp = new Comparator<Integer>() {
	    @Override
	    public int compare(Integer o1, Integer o2) {
		return o2 - o1;
	    }
	    
	};
	Arrays.sort( cakes, comp );
	Arrays.sort( gifts, comp );
	
	int cakesFromIndex = findMaxValueIndex( x - 1, cakes.length - 1, cakes );
	int sum = 0;
	int highIndex = gifts.length - 1;
	for( int i = cakesFromIndex; i < cakes.length; i ++ )
	{
	    int giftMaxValue = x - cakes[i];
	    highIndex = findMaxValueIndex( giftMaxValue, highIndex, gifts );
	    sum += ( gifts.length - highIndex ) ;
	}	
	System.out.println( sum );
    }
    
    private static int findMaxValueIndex( int maxValue, int highIndex, Integer[] srcArr )
    {
	// 已排序从大到小的数组,取值范围在 [0, fromIndex]
	int low = 0;
	int high = highIndex;
	int mid = ( low + high ) / 2;
	while( low <= high )
	{
	    mid = ( low + high ) / 2;
	    if( maxValue == srcArr[mid] )
	    {
		// 相等,还需判断所有相等的情况
		while( mid >= 1 && srcArr[mid - 1 ] == srcArr[mid])
		{
		    mid --;
		}
		return mid;
	    }else if( maxValue > srcArr[mid] )
	    {
		high = mid - 1;
	    }else
	    {
		low = mid + 1;
	    }
	}
	
	// 此时 low > high
	if( high < 0 )
	{
	    return 0;
	}
	if( srcArr[ high ] < maxValue )
	{
	    return high;
	}
	if( srcArr[low] < maxValue )
	{
	    return low;
	}
	if( low + 1 <= srcArr.length -1 )
	{
	    return low + 1;
	}else
	{
	    return srcArr.length -1;
	}
	
	
    }
}

JavaScript code

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function() {
    while (line = await readline()) {

        var strNumber = line.split(",");
        var cakes = new Array();
        for (var i = 0; i < strNumber.length; i++) {
            cakes[i] = parseInt(strNumber[i]);
        }

        line = await readline();
        var strNumber = line.split(",");
        var gifts = new Array();
        for (var i = 0; i < strNumber.length; i++) {
            gifts[i] = parseInt(strNumber[i]);
        }

        line = await readline();
        var x = parseInt(line);
        processBirthdayGift(cakes, gifts, x);

    }
}();

function processBirthdayGift(cakes, gifts, x) {
    // 从大到小排序
    var comp = function( a, b) {
        return b - a;        
    };
    cakes.sort( comp );
    gifts.sort( comp );

    var cakesFromIndex = findMaxValueIndex( x - 1, cakes.length - 1, cakes );
    var sum = 0;
    var highIndex = gifts.length - 1;

    for( var i = cakesFromIndex; i < cakes.length; i ++ )
    {
        var giftMaxValue = x - cakes[i];
        highIndex = findMaxValueIndex( giftMaxValue, highIndex, gifts );
        sum += ( gifts.length - highIndex ) ;
    }   
    console.log( sum );
}

function findMaxValueIndex(maxValue, highIndex, srcArr) {
    // 已排序从大到小的数组,取值范围在 [0, fromIndex]
    var low = 0;
    var high = highIndex;
    var mid = parseInt( (low + high) / 2 );
    while (low <= high) {
        mid = parseInt( (low + high) / 2 );
        if (maxValue == srcArr[mid]) {
            // 相等,还需判断所有相等的情况
            while (mid >= 1 && srcArr[mid - 1] == srcArr[mid]) {
                mid--;
            }
            return mid;
        } else if (maxValue > srcArr[mid]) {
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }
    // 此时 low > high
    if (high < 0) {
        return 0;
    }
    if (srcArr[high] < maxValue) {
        return high;
    }
    if (srcArr[low] < maxValue) {
        return low;
    }
    // should never come here
    if (low + 1 <= srcArr.length - 1) {
        return low + 1;
    } else {
        return srcArr.length - 1;
    }
}

(over)

Guess you like

Origin blog.csdn.net/ZiJinShi/article/details/134145268