算法刷题

1.判断镜像树

1.1判断二叉树是否对称

题目描述:Symmetric Tree

bool isSymmetric(TreeNode* root1,TreeNode *root2){
        if(root1 == NULL && root2 == NULL) return true;
        else if(root1 == NULL && root2 != NULL) return false;
        else if(root1 != NULL && root2 == NULL) return false;
        if(root1->val == root2->val){
            return isSymmetric(root1->left,root2->right) && isSymmetric(root1->right,root2->left);
        }else{
            return false;
        }
    }

其实与一道经典题型相类似
是谷歌的一道面试题,是翻转二叉树
有兴趣的童鞋可以看我的另一篇博文
面试经典

1.2判断n叉树是否对称(1.1的推广)

请参考面试经典

寻找重复数组中的唯一数字

Input: arr = [7, 3, 5, 5, 4, 3, 4, 8, 8]
Output: 7
例如:
arr中只有7是单身狗,其他数字都有两个

在此提供思路:

使用异或操作

类似题型:Missing Number

类似题型

题目描述:

Find All Numbers Disappeared in an Array

思路提示:

将nums[i]置换到其对应的位置nums[nums[i]-1]上去,比如对于没有缺失项的正确
顺序应该是[1, 2, 3, 4, 5, 6, 7, 8],而我们现在却是[4,3,2,7,8,2,3,1],我们需要把数>>字移动到正确的位置上去,比如第一个4就应该和7先交换个位置,以此类推,最后>>得到的顺序应该是[1, 2, 3, 4, 3, 2, 7, 8],我们最后在对应位置检验,如果nums[i]和>>i+1不等,那么我们将i+1存入结果res中即可. 即剑指offer面试题3.

将罗马数字转换为10进制阿拉伯数字

Input: IX
Output: 9

Input: VII
Output: 7

Input: MCMIV
Output: 1904

知识补充:

I 1
IV 4
V 5
IX 9
X 10
XL 40
L 50
XC 90
C 100
CD 400
D 500
CM 900
M 1000

在此提供思路:

将输入字符数组从后向前遍历,设置一个per指针和cur指针,cur指针指向当前值,per指针指向当前位置的上一个位置。如果pre<cur。则证明是一个符合数字,需要加上cur所指向的值减去per所指向的值。
举个例子:MCMIV. 首先cur指向V,而per指向I,所以result += 4.
如果是MCMIVI, 那么cur指向I,而per指向V. 因为I < V,所以result += 1.
我当初想的是从前向后遍历,这样处理明显没有上一个思路方便。
逆向思维很重要


二进制手表

题目描述:
Binary Watch
思路描述:
枚举,因为hours最多=11(hours没有12点只有0点),minutes最多=59

源码示例:

class Solution {
public:
    string getones(int hours,int minutes,int count1){
        int sum = 0;
        bitset<4> b(hours);
        bitset<6> c(minutes);
        sum = b.count() + c.count();
        if(sum == count1){
            if(minutes / 10 == 0){
                return (to_string(hours) + ":0" + to_string(minutes));
            }else{
                return to_string(hours) + ":" + to_string(minutes);
            }
         }else{
            return "";
        }
    }
    vector<string> readBinaryWatch(int num) {
        string str;
        vector<string> v1;
        for(int hours = 0;hours < 12;hours ++){
            for(int minutes = 0;minutes < 60;minutes ++){
                str = getones(hours,minutes,num);
                if(str != ""){
                    v1.push_back(str);
                }
            }
        }
        return v1;
    }
};

重复字母不毗邻的字符串

题目描述:
给定一个字符串,重排使得重排后字符串重复字母不相邻

输入:
abbccc
输出:
cbcbca
思路解析(贪心):
1.遍历字符串,记录字符出现次数
2.将元素存储进最大堆中
3.每次根据出现次数取出最大堆的根,然后将该两个字符出现次数减一,重新入堆。如果存在这样一种情况,就是堆,但是当前字符出现次数>1,则证明不存在满足题意的重排序列
请注意:
可能会出现这样的一种情况:比如输入序列为abbdcccc。第一次最大堆输出了c,但是第二次最大堆依旧输出c,但这并不影响结果的正确性。因为一个萝卜一个坑。字符在重排后的字符串的顺序并非按照出堆的顺序来(又不是堆排序)


给出最大整数

题目描述:
给定一组整数,给定该组整数的一个排列,使得总体最大

输入:
[17,7,2,45,72]
输出:
77245217

思路描述:
比较mn和nm之间的大小,如果mn<nm则n在前,m在后。反之m在前,n在后。


Path Sum III

题目描述:
path sum III
输入示例

      10
      /   \
     5   -3
    /  \    \
   3   2   11
  /  \   \
3  -2  1

输出示例

3
explanation:

  1. 5 -> 3
  2. 5 -> 2 -> 1
  3. -3 -> 11

思路描述:

1.将每个结点至根结点的和求出来,
2.然后计算A = tempsum - pathsum (tempsum是某节点至最终的根结点的路径上所有结点的值的和。)。
3.如果存在某个结点的值等于A。那么则存在对应的pathSum(pathSum = tempSum - A)

上面的输入实例如果计算区间和(从根节点到当前结点的路径和):

      10
      /   \
    15   7
    /  \    \
  18  17   18
  /  \    \
21 16 18

map<int,int> m1;
class Solution {
public:
    void getPathSum(TreeNode* root,int tempsum, int sum,int& count){
        if(root == NULL) return;
        tempsum += root->val;
        
        if(m1.count(tempsum - sum) != 0){
           // cout<<root->val<<endl;
            //cout<<tempsum<<endl;
            count += m1[tempsum - sum];
            cout<<count<<endl;
        }
        if(!m1.count(tempsum)){
            m1.insert(pair<int,int>(tempsum,1));
        }else{
            m1[tempsum] ++;
        }
        getPathSum(root->left,tempsum,sum,count);
        getPathSum(root->right,tempsum,sum,count);
        m1[tempsum] --;
        if(m1[tempsum] == 0){
            m1.erase(tempsum);
        }
    }
    int pathSum(TreeNode* root, int sum) {
        int count = 0;
        m1.clear();
        m1.insert(pair<int,int>(0,1));
        getPathSum(root,0, sum,count);
        return count;
    }
};

注意:

第11行的代码之所以采用count += m1[tempsum - sum]而不是count ++
是为了应对这种情况:
      0
      /
    10
    /
   3
上面的情况是因为计算13有两种情况:0 + 10 + 3 以及 10 + 3


二叉树两个结点的最低的共同祖先结点

题目描述:

给定一棵二叉树其中的两个结点,求这两个结点的最低的共同祖先结点

数据结构:

struct Node{
     struct Node* left;
     struct Node* right;
     struct Node* parent;
     int weight;
}

思路描述:

这道题其本质上是找到两个单链表的交集
首先,从A遍历到根,计算路径的长度。
其次,从B遍历到根,计算路径的长度。
最后,将指针设置在A和B处,并将较长路径的指针不断向前移动,直到两个路径的长度相等。
将两个指针同时向上移动,直到它们都在同一结点上,该结点就是最低的共同祖先结点


Minimum Moves to Equal Array Elements

题目描述:

Minimum Moves to Equal Array Elements

思路描述:

假设数组为a1,a2,a3,a4,a5,…an,不妨假设a1<a2<a3<…<an.
首先将a1移到与a2相等。需要将a1移到与a2相等,需要移动a2 - a1步,序列变成a2,a2,a3 + a2 - a1,…,an + a2 - a1.
继续将a2移到与(a3 + a2 - a1)相等,需要移动(a3 + a2 - a1) - a2步即a3 - a1步。所以此时序列变成a3 + a2 - a1, a3 + a2 - a1, a3 + a2 - a1 , … , an+a2-a1+a3-a1.
所以依此类推,将前n-1个数移动an-a1步。所以总的移动步数时a2 + a3 + … + an - (n-1) * a1(其中an是最大值,a1是最小值)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值