Leetcode刷题总结:650. 2 Keys Keyboard

题目: 求获取n个A的最小操作步骤的数目minStep

Initially on a notepad only one character ‘A‘ is present. You can perform two operations on this notepad for each step:

  1. Copy All: 只能全部复制,不能部分复制.
  2. Paste: 拷贝留在剪贴板上的字符

Given a number n. You have to get exactly n ‘A‘ on the notepad by performing the minimum number of steps permitted. Output the minimum number of steps to get n ‘A‘.

题解:

1.首先手写几个答案,可以看到:

  n=1, minSteps=0;

  n=2, 步骤:cp,minSteps=2

  n=3, 步骤:cpp, minSteps=3

  n=4, 步骤: cppp或者 cpcp(复制S[2]并粘贴一次),minSteps=4

  n=5, 步骤:cpppp=c+p*4,minSteps=5

  n=6, 步骤:c+p*5 或者 cp(cpp) (复制S[2]并粘贴2次) 或者 cpp(cp)(复制S[3]并粘贴1次), minSteps=5

  。。。。。

  n=12, 步骤:c+p*11

         或者 先取得“AA”然后c+p*5(这里5=(12-2)/2),S[n] = S[n/2] + 1+(n-2)/2 = S[n/2] + n/2

或者 先取得 “AAA”然后c+p*3(这里3=(12-3)/3),S[n] = S[n/3] + 1+(n-3)/3 = S[n/3] + n/3

或者 先取得“AAAA”然后c+p*2(这里2=(12-4)/4),S[n] = S[n/4] + 1+(n-4)/4 = S[n/4] + n/4

2. 从上面可以看到

  S[n] = min(S[n/i]+n/i) 其中i为能被n整除的数

  所以得到第一个思路代码如下:

class Solution {
public:
    int minSteps(int n) {
        std::vector<int> minSteps(n+1,0);
        for (int i = 2; i <= n; ++i) {
            minSteps[i] = i;
        }
        for (int i = 4; i <= n; ++i) {
            for (int j = 2; j < i; ++j) {
                if (i % j == 0) {
                    minSteps[i] = min(minSteps[i], minSteps[j]+i/j);
                }
            }
        }
        return minSteps[n];
    }
};

3. 提交审核通过,但是发现运行速度不行,看起来的复杂度是O(n*n),69ms,只打败了11%,再来看看有什么可以优化的:

  发现不需要中间层的遍历不需要j<i. 在j< i/2就可以了;再次提交运行,复杂度仍然还是O(n2), 62ms

4. 自己没有想到有什么能优化的地方,看了一下前面运行时间短的,发现内层循环的时候,循环条件是这样的:

for (int j = i/2; j >= 2 && j % i != 0; --j);

  分析一下可以得到原因:事实上不管n等于几,都应该尽可能地复制最多的字符,然后粘贴若干次,比如n=25=5*5,最快的应该是得到5个A然后copy1次粘贴4次,n=100=50*2,应该得到50,然后cp一次,修改代码如下:

class Solution {
public:
    int minSteps(int n) {
        std::vector<int> minSteps(n+1,0);
        for (int i = 2; i <= n; ++i) {
            minSteps[i] = i;
        }
        for (int i = 4; i <= n; ++i) {
            for (int j = i/2; j >= 2; --j) {
                if (i % j == 0) {
                    minSteps[i] = min(minSteps[i], minSteps[j]+i/j);
                    break;
                }
            }
        }
        return minSteps[n];
    }
};

复杂度基本上是O(n)

5. 还有更快的解答,看了一下用的是递归,分析了一下,快的原因是在这里使用递归,并没有重复计算,而且还省去了不必要的计算,复杂度远小于O(n),

比如n=100,我的方法,要计算100+,

这里用递归,只需要计算n=100,n=50,n=25,n=5

时间: 2024-08-10 17:05:57

Leetcode刷题总结:650. 2 Keys Keyboard的相关文章

【leetcode刷题笔记】Validate Binary Search Tree

Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys

【leetcode刷题笔记】Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For example, 1 / 2 3 T

leetcode 刷题之路 63 Binary Tree Zigzag Level Order Traversal

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree {3,9,20,#,#,15,7}, 3 / 9 20 / 15 7 return its zig

leetcode 刷题之路 64 Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree. Note: You may assume that duplicates do not exist in the tree. 给出二叉树的中序遍历和后序遍历结果,恢复出二叉树. 后序遍历序列的最后一个元素值是二叉树的根节点的值,查找该元素在中序遍历序列中的位置mid,根据中序遍历和后序遍历性质,有: 位置mid以前的序列部分为二叉树根节点左子树中

【leetcode刷题笔记】Longest Consecutive Sequence

Given an unsorted array of integers, find the length of the longest consecutive elements sequence. For example,Given [100, 4, 200, 1, 3, 2],The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4. Your algorithm should run in

【leetcode刷题笔记】Remove Duplicates from Sorted Array II

Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For example,Given sorted array A = [1,1,1,2,2,3], Your function should return length = 5, and A is now [1,1,2,2,3]. 题解: 设置两个变量:右边kepler和前向游标forward.如果当前kepeler所指的元素和

【leetcode刷题笔记】Restore IP Addresses

Given a string containing only digits, restore it by returning all possible valid IP address combinations. For example:Given "25525511135", return ["255.255.11.135", "255.255.111.35"]. (Order does not matter) 题解:深度优先搜索.用resul

【leetcode刷题笔记】Path Sum

Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example:Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ 7 2 1 return true, as t

【leetcode刷题笔记】Insertion Sort List

Sort a linked list using insertion sort. 题解:实现链表的插入排序. 要注意的地方就是,处理链表插入的时候尽量往当前游标的后面插入,而不要往前面插入,后者非常麻烦.所以每次利用kepeler.next.val和head.val比较大小,而不是kepeler.val和head.val比较大小,因为如果用后者,要把head指向的节点插入到kepeler指向的节点的前面,如果kepeler指向的节点是头结点,就更麻烦了. 代码如下: 1 /** 2 * Defi

【leetcode刷题笔记】Max Points on a Line

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. 题解: 思路比较简单,每条直线都可以表示为y=kx+b,所以对于任意三点,如果它们共线,那么它们中任意两点的斜率都相等. 所以就遍历points数组,对其中的每一个元素计算它和位于它后面的数组元素的斜率并保存在一个hashmap中. 这个hashmap的键就是两点构成直线的斜率,值就是和当前元素po