3月19日阿里实习笔试题

第一题

给定一个整数n(确保为偶数),以及长度为n的数组a,可以对数组a中的元素进行+1或者减一的操作,求最少操作多少次,能够使数组中有一半元素为平方数(如2,4,8…)。
示例输入:
4
4 7 12 13
示例输出:
2
解释:
只需修改7为9,就有一半的数是平方数了。且操作次数为2

题解
使用二分法对每个数求其离最近平方数的差值的最小值的绝对值。然后将结果排序,求前面一半的和就可以了
AK代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	var n int
	fmt.Scanln(&n)
	arr := make([]int, n)
	for i:=0; i<n; i++ {
		var temp int
		fmt.Scan(&temp)
		arr[i] = isSquare(temp)
	}
	sort.Ints(arr)
	result := 0
	for i:=0; i<n/2; i++ {
		result += arr[i]
	}
	fmt.Println(result)
}

func isSquare(x int) int {
	left, right := 0, x
	for left < right {
		mid := left + (right-left) / 2
		//fmt.Println(left, right, mid)
		if mid*mid > x {
			right = mid - 1
		} else {
			left = mid + 1
		}
	}
	t := left*left
	if t == x {
		return 0
	} else if t < x {
		return min(x-t, (left+1)*(left+1)-x)
	}
	return min(x-(left-1)*(left-1), t-x)
}


func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

第二题

给定两个等长数组a,b,求满足i<j<k且a[i]<=a[j]<=a[k]的条件下,求b[i]+b[j]+[k]的最小值。

这道题题目好像出错了,笔试最后五分钟面试官改了,a[i]<=a[j]<=a[k]变为a[i]<a[j]<a[k]。而且测试用例也有问题。

输入用例:
9 8 6 7 7 2 9 2
9 1 10 8 6 4 8 6
输出用例:
24(我怎么算都是22)

代码(通过率百分之78):

package main

import (
	"fmt"
	"math"
)

func main() {
	var n int
	fmt.Scanln(&n)
	a := make([]int, n)
	b := make([]int, n)
	for i:=0; i<n; i++ {
		var temp int
		if i == n-1 {
			fmt.Scanln(&temp)
		} else {
			fmt.Scan(&temp)
		}
		a[i] = temp
	}
	for i:=0; i<n; i++ {
		var temp int
		if i == n-1 {
			fmt.Scanln(&temp)
		} else {
			fmt.Scan(&temp)
		}
		b[i] = temp
	}
	m := math.MaxInt32
	for i:=0; i<n-3; i++ {
		for j:=i+1; j<n-2; j++ {
			if a[i] > a[j] {
				continue
			}
			for k:=j+1; k<n-1; k++ {
				if a[j] > a[k] {
					continue
				}
				//fmt.Println(i, j, k)
				m = min(m, b[i]+b[j]+b[k])
			}
		}
	}
	if m == math.MaxInt32 {
		fmt.Println(-1)
	}
	fmt.Println(m)
}




func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

第二题

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
//给定两个等长数组a,b,求满足i<j<k且a[i]<a[j]<a[k]的条件下,求b[i]+b[j]+b[k]的最小值。
// 考虑动态规划,dp[i][j] 	数组下标0~i中选符合条件的j个数的最小值
func main() {
	a := []int{9, 8, 6, 7, 7, 2, 9, 2}
	b := []int{9, 1, 10, 8, 6, 4, 8, 6}
	n := len(a)
	dp := make([][]int, n)
	for i := 0; i < n; i++ {
		dp[i] = []int{b[i], 1000, 1000} //初始化最大值
	}

	for i := 0; i < n; i++ {
		for k := 0; k < i; k++ {
			for j := 1; j < 3; j++ {
				if a[i] > a[k] {
					dp[i][j] = min(dp[i][j], dp[k][j-1]+b[i])
				}
			}
		}
	}
	ans := math.MaxInt32
	for i := 0; i < n; i++ {
		if dp[i][2] < ans {
			ans = dp[i][2]
		}
	}
	fmt.Println(ans)
}