Leetcode进阶之路——Weekly Contest 127

37 篇文章 0 订阅

1005. Maximize Sum Of Array After K Negations

Given an array A of integers, we must modify the array in the following way: we choose an i and replace A[i] with -A[i], and we repeat this process K times in total. (We may choose the same index i multiple times.)
Return the largest possible sum of the array after modifying it in this way.
Example 1:
Input: A = [4,2,3], K = 1
Output: 5
Explanation: Choose indices (1,) and A becomes [4,-2,3].
Example 2:
Input: A = [3,-1,0,2], K = 3
Output: 6
Explanation: Choose indices (1, 2, 2) and A becomes [3,1,0,2].
Example 3:
Input: A = [2,-3,-1,5,-4], K = 2
Output: 13
Explanation: Choose indices (1, 4) and A becomes [2,3,-1,5,4].

输入数组A和数字K,对A中的数做取负操作,求K次该操作后所得数组元素之和最大值
容易想到

  1. 如果A中负数个数N大于等于K,则对A中前K个最小的负数取反即可
  2. 如果负数个数N小于K,则将所有负数先取反,然后对最小的数取反K-N次
class Solution {
public:
    // 排序规则 
    static bool largestSumAfterKNegationscmp(const int &a, const int &b)
	{
		int aa = abs(a), bb = abs(b);
		return aa > bb;
	}
	int largestSumAfterKNegations(vector<int>& A, int K) {
		int sum = 0, cnt = 0;
		for (int i = 0; i < A.size(); ++i)
		{
			sum += A[i];
			if (A[i] < 0) cnt++;
		}
		sort(A.begin(), A.end(), largestSumAfterKNegationscmp);
		if (cnt >= K)
		{
			for (int i = 0; i < A.size() && K; ++i, --K)
				if (A[i] < 0)
					A[i] = -A[i], sum += 2 * A[i];
		}
		else
		{
			K -= cnt;
			for (int i = 0; i < A.size(); ++i)
				if (A[i] < 0)
					A[i] = -A[i], sum += 2 * A[i];
			if (K % 2 == 1) sum -= A[A.size() - 1] * 2;
		}
		return sum;
	}
};

更一般的做法,采用priority_queue可实现, 用小顶堆,每次对列首元素取反,N次后求和:

class Solution {
public:
	int largestSumAfterKNegations(vector<int>& A, int K) {
		priority_queue<int, vector<int>, greater<int>> pq;
        for(int i = 0; i < A.size(); ++i)
        {
            pq.emplace(A[i]);
        }
        for(int i = 0; i < K; ++i)
        {
            int a = pq.top();
            pq.pop();
            a = -a;
            pq.emplace(a);
        }
        int sum = 0;
        while(!pq.empty())
        {
            sum += pq.top();
            pq.pop();
        }
        return sum;
	}
};

1006. Clumsy Factorial

Normally, the factorial of a positive integer n is the product of all positive integers less than or equal to n. For example, factorial(10) = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1.
We instead make a clumsy factorial: using the integers in decreasing order, we swap out the multiply operations for a fixed rotation of operations: multiply (*), divide (/), add (+) and subtract (-) in this order.
For example, clumsy(10) = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1. However, these operations are still applied using the usual order of operations of arithmetic: we do all multiplication and division steps before any addition or subtraction steps, and multiplication and division steps are processed left to right.
Additionally, the division that we use is floor division such that 10 * 9 / 8 equals 11. This guarantees the result is an integer.
Implement the clumsy function as defined above: given an integer N, it returns the clumsy factorial of N.
Example 1:
Input: 4
Output: 7
Explanation: 7 = 4 * 3 / 2 + 1
Example 2:
Input: 10
Output: 12
Explanation: 12 = 10 * 9 / 8 + 7 - 6 * 5 / 4 + 3 - 2 * 1

给定一个数字N,求出对应的clumsy(N)值
不可能硬求,那就先找规律,考虑到加减乘除的优先级,可将三个符号(四个数字)作为一组,最后将每组的数字相减即可,但考虑到减法,所以除了第一组,后面都要将加法修改为减法
代码如下:

class Solution {
public:
    int clumsy(int N) {
		if (N < 3) return N;
		int sum = N * (N - 1) / (N - 2) + (N - 3);
		N -= 4;
		while (N / 4)
		{
			sum -= N * (N - 1) / (N - 2) - (N - 3);
			N -= 4;
		}
		switch (N)
		{
		case 1: sum -= N; break;
		case 2: sum -= N * (N - 1); break;
		case 3: sum -= N * (N - 1) / (N - 2); break;
        }
		return sum;
	}
};

1007. Minimum Domino Rotations For Equal Row

In a row of dominoes, A[i] and B[i] represent the top and bottom halves of the i-th domino. (A domino is a tile with two numbers from 1 to 6 - one on each half of the tile.)
We may rotate the i-th domino, so that A[i] and B[i] swap values.
Return the minimum number of rotations so that all the values in A are the same, or all the values in B are the same.
If it cannot be done, return -1.
Example 1:
Input: A = [2,1,2,4,2,2], B = [5,2,6,2,3,2]
Output: 2
Explanation:
The first figure represents the dominoes as given by A and B: before we do any rotations.
If we rotate the second and fourth dominoes, we can make every value in the top row equal to 2, as indicated by the second figure.
Example 2:
Input: A = [3,5,1,2,3], B = [3,6,3,3,4]
Output: -1
Explanation:
In this case, it is not possible to rotate the dominoes to make one row of values equal.

给定两个数组,交换对应第i位的数组,使得有一个数组所有数字全相同,求最少需要的交换次数
我的想法很简单也略暴力,先判断两个数组是否能满足交换后所有数字都相同,然后分别求各自的最少交换次数
再将两个数组各自的次数取小值

class Solution {
public:
    int minDominoRotations(vector<int>& A, vector<int>& B) {
		int len = A.size();
		if (len < 2) return 0;
		vector<int> v(10, 0), va(10, 0), vb(10, 0);
		for (int i = 0; i < len; ++i)
		{
			v[A[i]]++;
            va[A[i]]++, vb[B[i]]++;
			if (A[i] != B[i])
			{
				v[B[i]]++;
			}
		}
        bool flag1 = false, flag2 = false;
        int cnt1 = 0, cnt2 = 0;
		if(v[A[len - 1]] == len)
        {
            flag1 = true;
            
            if(vb[A[len - 1]] == 0) return 0;
            else
                cnt1 = min(min(len - va[A[len - 1]], va[A[len - 1]]), min(len - vb[A[len - 1]], vb[A[len - 1]]));
        }
        if(B[len - 1] != A[len - 1] && v[B[len - 1]] == len)
        {
            flag2 = true;
            if(va[A[len - 1]] == 0) return 0;
            else
                cnt2 = min(min(len - vb[B[len - 1]], vb[B[len - 1]]), min(len - va[B[len - 1]], va[B[len - 1]]));
        }
        if(flag1 || flag2)
        {
            if(!flag1) return cnt2;
            if(!flag2) return cnt1;
            return min(cnt1, cnt2);
        }
        return -1;
	}
};

1008. Construct Binary Search Tree from Preorder Traversal

Return the root node of a binary search tree that matches the given preorder traversal.
(Recall that a binary search tree is a binary tree where for every node, any descendant of node.left has a value < node.val, and any descendant of node.right has a value > node.val. Also recall that a preorder traversal displays the value of the node first, then traverses node.left, then traverses node.right.)
Example 1:
Input: [8,5,1,7,10,12]
Output: [8,5,10,1,7,null,12]

典型的根据先序遍历构建BST,递归可解
首元素为当前的head,其后比它大的元素为其右子树,第一个出现的大元素为其右子树的head,其后比它小的元素为其左子树,第一个出现的小元素为其左子树的head,若找不到比它大(小)的元素,则所构建的向量空间为0,返回NULL即可,最后递归调用构建可得。
代码如下:

class Solution {
public:
    TreeNode* bstFromPreorder(vector<int>& preorder) {
		int len = preorder.size();
		if (len == 0) return NULL;
		if (len == 1) return new TreeNode(preorder[0]);
		TreeNode* head = new TreeNode(preorder[0]);
		vector<int> lc, rc;
        for(int i = 1; i < len; ++i)
            if(preorder[i] < preorder[0]) lc.emplace_back(preorder[i]);
            else rc.emplace_back(preorder[i]);
        head->left = bstFromPreorder(lc);
        head->right = bstFromPreorder(rc);
		return head;
	}
};

某些题目的理解与解法可能有些复杂,若有更好的解法可提出互相交流~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值