美文网首页
剑指offer.C++.code46-50

剑指offer.C++.code46-50

作者: 小异_Summer | 来源:发表于2018-03-22 20:44 被阅读0次

46. 圆圈中最后剩下的数【约瑟夫环问题】

  • 有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
// Solution:(1)使用环形链表模拟,时间复杂度O(mn),空间复杂度O(n);
//          (2)直接找出最后一个数字规律
class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if (n < 1 || m < 1) 
            return -1;
        list<int> numbers;
        for (int i = 0; i < n; i ++) 
            numbers.push_back(i);
        list<int>::iterator cur = numbers.begin();
        while (numbers.size() > 1) {
            for (int i = 1; i < m; i ++) {
                cur ++;
                if (cur == numbers.end())    // 模拟环尾
                    cur = numbers.begin();
            }
            list<int>::iterator deleteIt = cur;
            cur ++;
            if (cur == numbers.end()) 
                cur = numbers.begin();
            numbers.erase(deleteIt);
        }
        return *(cur);
    }
};
// Solution:(1)使用环形链表模拟,时间复杂度O(mn),空间复杂度O(n);
//          (2)直接找出最后一个数字规律,f(n,m) = 0, n=1,时间O(n),空间O(1)
//                                  f(n,m) = [f(n-1, m)+m]%n, n>1
class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if (n < 1 || m < 1) 
            return -1;
        int last = 0;
        for (int i = 2; i <= n; i ++)
            last = (last + m) % i;
        return last;
    }
};

47. 求1+2+...+n【发散思维】

  • 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
// Solution:(1)利用构造函数求解
class Temp {
public:
    Temp() { N ++; Sum += N;}
    static void Reset() { N = 0; Sum = 0;}
    static unsigned int GetSum() { return Sum;}
private:
    static unsigned int N;
    static unsigned int Sum;
};

unsigned int Temp::N = 0;
unsigned int Temp::Sum = 0;

class Solution {
public:
    int Sum_Solution(int n) {
        Temp::Reset();
        Temp *a = new Temp[n];
        delete []a;
        a = NULL;
        return Temp::GetSum();
    }
};
// Solution:(2)利用虚函数求解,一个函数递归,一个函数判断终止条件
class A;
A* Array[2];

class A {
    public:
    virtual unsigned int Sum(unsigned int n) {
        return 0;
    }
};

class B: public A {
    public:
    virtual unsigned int Sum(unsigned int n) {
        return Array[!!n]->Sum(n-1) + n;
    }
};

class Solution {
public:
    int Sum_Solution(int n) {
        A a;
        B b;
        Array[0] = &a;
        Array[1] = &b;
        int value = Array[1]->Sum(n);
        return value;
    }
};
// Solution:(3)利用函数指针求解
typedef int (*fun) (int);   
class Solution {
public:
    static int Sum_terminator(int n) {
        return 0;
    }
    static int Sum_Solution(int n) {
        static fun f[2] = {Sum_terminator, Sum_Solution};
        return n + f[!!n](n-1);
    }
};

48. 不用加减乘除做加法

  • 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
// Solution:位运算
class Solution {
public:
    int Add(int num1, int num2)
    {
        int sum, carry;
        do {
            sum = num1 ^ num2;
            carry = (num1 & num2) << 1;
            
            num1 = sum;
            num2 = carry;
        } while (num2 != 0);
        return num1;
    }
};

49. 把字符串转换成整数

  • 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

输入描述:
输入一个字符串,包括数字字母符号,可以为空
输出描述:
如果是合法的数值表达则返回该数字,否则返回0
示例1
输入
+2147483647
1a33
输出
2147483647
0

// 考虑:(1)输入""; (2)输入非0-9; (3)输入"+/-"等; (4)溢出
class Solution {
public:
    int StrToInt(string str) {
        int gFlag = -1;
        int len = str.size();
        if (len  == 0) {
            gFlag = 1;
            return 0;
        }
        int minus = 1;
        long long num = 0;
        
        int i = 0;
        if (str[i] == '+') {
            i ++;
        } else if (str[i] == '-') {
            i ++;
            minus = -1;
        }
        
        while (str[i] != '\0') {
            if (str[i] >= '0' && str[i] <= '9') {
                num = num*10 + str[i]-'0';
                i ++;
                if (((minus > 0) && (num > 0x7FFFFFFF)) || 
                    ((minus < 0) && (num > 0x80000000))) {
                    num = 0;
                    gFlag = 2;
                    break;
                }
            } else {
                num = 0;
                gFlag = 3;
                break;
            }
        }
        return (int)minus*num;
    }
};

50. 树中两个结点的最低公共祖先

  • 输入两个结点,求他们的最低公共祖先
  • 二叉树:判断两个结点与当前结点的大小关系,第一个在两节点之间的值即最低公共祖先。
solution
  • 非二叉树,有指向父节点的指针:(转换为求两个链表第一个公共结点)
solution
  • 非二叉树,没有指向父节点的指针: 判断子树中同时包含两个结点,并判断该节点的子节点子树不同时包含两个结点,该结点就是最低公共祖先。使用数组保存两个结点所在的路径,以减少重复计算子树情况。
solution1
solution2
soluntion3
bool GetNodePath(TreeNode * pRoot, TreeNode * pNode, list<TreeNode *> &path) {
    if (pRoot == pNode) 
        return true;
    path.push_back(pRoot);
    bool found = false;
    vector<TreeNode *>::iterator i = pRoot->children.begin();
    while (! found && i < pRoot->children.end()) {
        found = GetNodePath(*i, pNode, path);
        i ++;
    }
    if (! found) 
        path.pop_back();
    return found;
}

TreeNode * GetLastCommonNode(const list<TreeNode*> &path1, const list<TreeNode*> &path2) {
    list<TreeNode*>::const_iterator iterator1 = path1.begin();
    list<TreeNode*>::const_iterator iterator2 = path2.begin();
    TreeNode* pLast = NULL;
    while (iterator1 != path1.end() && iterator2 != path2.end()) {
        if (*iterator1 == *iterator2)
            pLast = *iterator1;
        iterator1 ++;
        iterator2 ++;
    }
    return pLast;
}

TreeNode * GetLastCommonParent(TreeNode * pRoot, TreeNode * pNode1, TreeNode * pNode2) {
    if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL)
        return NULL;
    List<TreeNode *> path1;
    GetNodePath(pRoot, pNode1, path1);
    List<TreeNode *> path2;
    GetNodePath(pRoot, pNode2, path2);
    return GetLastCommonNode(path1, path2);
}

相关文章

  • 剑指offer.C++.code46-50

    46. 圆圈中最后剩下的数【约瑟夫环问题】 有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数...

  • 剑指

    遥望中原九点烟,风云直上七重天。 今朝再向江湖去,一剑流星谁比肩? 2011.10(1488)

  • 剑指

    1. 二维数组中查找 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照...

  • 全网最全剑指offer题目解答

    【剑指offer】Java版代码(完整版) 【剑指offer】1-10题 【剑指offer】11-20题 【剑指o...

  • 剑指offer

    第一题:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,...

  • 剑指BAT

    Android工作5年半了,一毕业就开始做这行。在现在这家公司工作了3年整,最近有换工作的打算,所以在猎聘...

  • 《剑指offer》

    4.调整数组顺序使奇数位于偶数前面 题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇...

  • 气剑指

    “聚气于指尖,凝其成剑,利可断金。”牢头对身边的狱卒说。 只见牢头举起的右手指尖逐渐变红,转而变白,隐隐发出音量很...

  • 剑指offer

    二维数组中查找数在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到...

  • 剑指苍穹

    逆天命,斩苍穹,吾乃修士,率性而为!《剑指苍穹》是一款逍遥仙侠MMORPG——群魔阻道,斩群魔;妖邪拦路,诛妖邪,...

网友评论

      本文标题:剑指offer.C++.code46-50

      本文链接:https://www.haomeiwen.com/subject/gwvjqftx.html