leetcode:杂项、矩阵、二分查找等

292. 尼姆游戏(Nim Game)

有一堆石头,两个人轮流从中取出1到3块石头,取得最后一块石头的是胜者。
思路
若石头总数n是4的倍数,则后手有必胜法:每次取完后,保持剩余石头数是4的倍数。
若n不是4的倍数,则先手就有必胜法了。

        return n%4 != 0;

7. 翻转整数

考虑正负数,将整数的各位颠倒。如果颠倒后的结果溢出了,就输出0。
这里为了方便地处理溢出问题,使用一个long变量保存结果。

class Solution {
   
public:
    int reverse(int x) {
        long res = 0;
        while(x) {
            res = res*10 + x%10;
            x /= 10;
        }
        return (res<INT_MIN || res>INT_MAX) ? 0 : res;
    }
};

安卓九宫格解锁有多少种可能

思路
深度优先遍历,期间判断当前位置和上一个位置之间是不是还存在一个数,如果是,该数之前有没有被访问过。如果存在且该数还没有被访问过,就跳过。

代码:

int book[10]={
  0};
int num[10]={
  0};
int ans=0;

int m[10][10]={
  0};

void dfs(int cnt) {
    if(cnt>4) ans++;

    for(int i = 1; i<=9; i++){
        if(book[i]==0){
            if(m[i][num[cnt-1]] && book[ m[i][num[cnt-1]] ]==0) //如果当前i和上一个位置之间还存在一个节点,同时该节点没有被访问过          
                continue;            
            num[cnt] = i;//该手势的第cnt位是i
            book[i] = 1;//标记数字i
            dfs(cnt+1);
            book[i] = 0;//撤销数字i的标记
        }  
    }
}


int main() {
    int n;
    //while(cin>>n) {
   
    //  ;
    //}
    m[1][3]=2;
    m[4][6]=5;
    m[7][9]=8;
    m[1][7]=4;
    m[2][8]=5;
    m[3][9]=6;
    m[1][9]=5;
    m[3][7]=5;
    for(int i = 1; i<=9; i++)
        for(int j = i+1; j<=9; j++)
            m[j][i] = m[i][j];
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

33. 在翻转的排序数组中查找某个数

假设有一个排序的按未知的旋转轴旋转的数组(比如,0 1 2 4 5 6 7 可能成为4 5 6 7 0 1 2)。给定一个目标值进行搜索,如果在数组中找到目标值返回数组中的索引位置,否则返回-1。
你可以假设数组中不存在重复的元素。
思路
二分查找,主要是要考虑全面。考虑nums[mid]落在前半段还是后半段。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1;
        int mid=0;
        while(left<=right)
        {
            mid=(left+right)/2;
            if(nums[mid]==target)
                return mid;
            //如果mid落在了后半段
            if(nums[mid]<nums[left])
            {
                if(nums[mid]<target && target<=nums[right])
                    left=mid+1;
                else
                    right=mid-1;
            }
            //如果mid落在了前半段
            else
            {
                if(nums[mid]>target && target>=nums[left])
                    right=mid-1;
                else 
                    left=mid+1;
            }
        }
        return -1;
    }
};

258. 将各位数相加(Add Digits)

将一个整数的各位数相加,再将相加结果的各位数相加……直到相加结果是个位数结束。求该个位数。
例:456->4+5+6=15->1+5=6
思路

[n*10^(m)]%9 = [n*99...9 + n]%9 = n%9
num%9 = (num各位相加的和)%9 = …… = (所求个位数)%9

设所求个位数为a,则

  • 当num%9==0时,a=9;
  • 当num%9!=0时,a=num%9

上面的讨论也可以用一句话描述:

return (num-1)%9+1;

319. 翻转灯泡

有n盏灯,初始状态是全灭。第1次,全部打开;第2次,每2盏灯翻转状态;第i次,每i盏灯翻转状态;……;第n次,最后一盏灯翻转状态。求此时亮着的灯的个数。
思路
第i盏灯如果亮着,说明它有奇数个因子。对i而言,除了1和i本身,若p*q=i,则i有成对的因子,除非p=q,即i是平方数。所以,题目实际上是求n以内平方数的个数。

    return (int)Math.sqrt(n);

13. 罗马数字转换成阿拉伯数字

罗马数字有如下符号:
Ⅰ(1)Ⅴ(5)Ⅹ(10)L(50)C(100)D(500)M(1000)

计数规则:

  1. 若干相同数字连写表示的数是这些罗马数字的和,如III=3;
  2. 小数字在大数字前面表示的数是用大数字减去小数字,如IV=4;
  3. 小数字在大数字后面表示的数是用大数字加上小数字,如VI=6;

组合规则:

  1. 基本数字Ⅰ、X 、C 中的任何一个,自身连用构成数目,或者放在大数的右边连用构成数目,都不能超过三个;放在大数的左边只能用一个。
  2. 不能把基本数字 V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目,只能使用一个。
  3. V 和 X 左边的小数字只能用Ⅰ。
  4. L 和 C 左边的小数字只能用X。
  5. D 和 M 左 边的小数字只能用 C 。

思路
从前往后遍历罗马数字,如果某个数比前一个数小,则把该数加入到结果中;反之,则在结果中两次减去前一个数并加上当前这个数;

class Solution {
   
public:
    int romanToInt(string s) {
        int sum=0;
        int pre=0;
        for(int i=0;i<s.size();i++){
            int c;
            switch(s[i]){
                case 'I':c=1;break;
                case 'V':c=5;break;
                case 'X':c=10;break;
                case 'L':c=50;break;
                case 'C':c=100;break;            
                case 'D':c=500;break;
                case 'M':c=1000;break;
            }
            if(c>pre)   sum+=c-2*pre;
            else    sum+=c;
            pre=c;
        }
        return sum;
    }
};

12. 阿拉伯数字转换成罗马数字

思路
按照个-十-百-千的顺序,依次将相应位上的阿拉伯数字转换成罗马数字。如:
十位上的数字(表示0、10、20、……、90)分别表示为”“,”X”, “XX”,”XXX”,”XL”,”L”,”LX”,”LXX”,”LXXX”,”XC”,添加到最终的罗马数字字符串中去。

class Solution {
public:
    string intToRoman(int num) {
        string thousand[4] = {
  "", "M", "MM","MMM"};  
        string hundred[11] = {
  "", "C","CC","CCC","CD","D","DC","DCC","DCCC","CM"};   
        string ten[11] = {
  "", "X", "XX","XXX","XL","L","LX","LXX","LXXX","XC"};   
        string one[11] = {
  "", "I","II","III","IV","V","VI","VII","VIII","IX"};   
        string result = "";  
        string* trans[4] = {
  one, ten, hundred, thousand};  
        int index = 0;  
        while (num > 0) {  
            result = trans[index][num % 10] + result;  
            num = num / 10;  
            index++;  
        }  
        return result;  
    }  
};  

20. 合法的括号(Java)

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
思路:
利用Stack,思路也比较简单,当遇上(或者[或者{ ,就将它们压栈;当遇上)或者]或者},如果栈顶元素是对应的左括号,就将该左括号弹出。最后,如果栈为空,就说明合法,否则不合法。

public class Solution {
    public boolean isValid(String s) {
        Stack stack = new Stack<>();
        for(int i=0;i<s.length();i++) {
            char c=s.charAt(i);
            if(c=='(' || c=='[' || c=='{') {
                stack.push(c);
            }
            if(c==')') {
                if(stack.empty()) return false;
                if((char)stack.peek()=='(') stack.pop();
                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值