力扣算法题-1363.形成三的最大倍数

题目

给你一个整数数组 digits,你可以通过按任意顺序连接其中某些数字来形成 3 的倍数,请你返回所能得到的最大的 3 的倍数。
由于答案可能不在整数数据类型范围内,请以字符串形式返回答案。

如果无法得到答案,请返回一个空字符串。

示例 1:
输入:digits = [8,1,9]
输出:“981”

示例 2:
输入:digits = [8,6,7,1,0]
输出:“8760”

示例 3:
输入:digits = [1]
输出:""

示例 4:
输入:digits = [0,0,0,0,0,0]
输出:“0”

提示:
1 <= digits.length <= 10^4
0 <= digits[i] <= 9
返回的结果不应包含不必要的前导零。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-multiple-of-three

思路

思路基础:
1、某数每位之和为三的倍数,则该数为三的倍数;
2、数组中的数全部在0-9范围内,除去0之外,取1-9任意三个数,包括重复的;
这三个数中,必然存在一个数,两个数,或者三个数之和为三的倍数(按照余数计算可以论证)
因此可知,1-9中的数字 最多舍弃两个数。

由以上基础可知,需要考虑以下几种情况:
1、全部数之和为三的倍数;
2、全部数之和不为三的倍数,舍弃一位后满足和为三的倍数;
3、全部数之和不为三的倍数,舍弃两位后满足和为三的倍数;
4、考虑到全部为零,或者除零外的数字之和不为三的倍数的情况,需要输出零。

输出数,按照由大到小,高位到低位显示;

程序

int cmp(const void *a, const void *b){
    return *(int*)a - *(int*)b;
}
char* largestMultipleOfThree(int* digits, int digitsSize) {
	char* str = (char*)malloc(sizeof(char) * 10001);
	/*首先进行数组排序处理*/
	qsort(digits, digitsSize, sizeof(int), cmp);
	int i, j, k, m, sum = 0, zcnt = 0;
    
	str[0] = '\0';
	/*若数组长度为0,返回为空*/
	if (digitsSize <= 0) return str;
	
	/*获取0的个数*/
	while (zcnt<digitsSize && digits[zcnt] == 0) {
		zcnt++;
	}
	/*若全部是0的情况*/
	if (zcnt > 0 && zcnt == digitsSize) {
		str[0] = '0';
		str[1] = '\0';
		return str;
	}
	/*求所有数之和*/
	for (i = digitsSize - 1; i >= zcnt; i--) {
		sum += digits[i];
	}
    /*若全部数和为3的倍数*/
	if (sum % 3 == 0) {
		for (i = digitsSize - 1, j = 0; i >= zcnt; i--) {
			str[j] = (char)(digits[i] + '0');
			j++;
		}
		/*拼接0*/
		for (; zcnt>0; j++, zcnt--) {
			str[j] = '0';
		}
		str[j] = '\0';
		return str;
	}
	else {
	   /*判断按照舍弃一个数的情况,能否和为3的倍数,舍弃规则按照从小到大*/
		for (k = zcnt; k<digitsSize; k++) {
			if ((sum - digits[k]) % 3 == 0) {
				break;
			}
		}
		/*若存在舍弃一个数和为3的倍数的情况*/
		if (k<digitsSize) {
			for (i = digitsSize - 1, j = 0; i >= zcnt; i--) {
				if (i == k) {
					continue;
				}
				str[j] = (char)(digits[i] + '0');
				j++;
			}
			for (; zcnt>0; j++, zcnt--) {
				str[j] = '0';
			}
			str[j] = '\0';
			return str;
		}
		else {
			int iflag = 0;
			/*判断按照舍弃两个数的情况,能否和为3的倍数,舍弃规则按照从小到大*/
			for (k = zcnt; k<digitsSize - 1; k++) {
				for (m = k + 1; m<digitsSize; m++) {
					if ((sum - digits[k] - digits[m]) % 3 == 0) {
						iflag = 1;
						break;
					}
				}
				if (iflag) break;
			}
			/*若存在舍弃两个数和为3的倍数的情况*/
			if (k<digitsSize - 1 && m < digitsSize) {
				for (i = digitsSize - 1, j = 0; i >= zcnt; i--) {
					if (i == k || i == m) {
						continue;
					}
					str[j] = (char)(digits[i] + '0');
					j++;
				}
				for (; zcnt>0; j++, zcnt--) {
					str[j] = '0';
				}
				str[j] = '\0';
				return str;
			}
		}
	}
	/*若不为0的数据之和不为3,且数组中存在0,返回0 */
	if (zcnt > 0) {
		str[0] = '0';
		str[1] = '\0';
		return str;
	}
	/*若没有匹配到和为3倍数的情况,返回为空*/
	return str;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值