简单的leetcode题(四)

Roman to Integer

Given a roman numeral, convert it to an integer.

Input is guaranteed to be within the range from 1 to 3999.

把一个罗马数字转换成十进制,范围是1到3999

为了编个程,把罗马有数字学了一遍。。。

简单说一下罗马数字的构造规则
首先罗马数字由7个基本数字组成
I=1, V=5, X=10, L=50, C=100, D=500, M=1000,规则如下:

  1. 单个数字代表本身,如上所示
  2. 数字重复几次,代表自身的几倍,但是最多三次
  3. 如果数字左边的数小于该数,则减去左边的数例如IV就是4,但是左边的仅限于I,X,C,左减时不可跨越一个位数。比如,99不可以用IC(100 - 1)表示,而是用XCIX([100 - 10] + [10 - 1])表示。(等同于阿拉伯数字每位数字分别表示。), 左减数字必须为一位,比如8写成VIII,而非IIX
  4. 如果数字右边的数小于该数,则加上右边的数例如VI就是6,右加数字不可连续超过三位,比如14写成XIV,而非XIIII
  5. 如果某个数字上面划线,则表示该数字乘以1000

其实在分析了题目之后,就能明白,对规则的判断并不是我们所需要考虑的,因为既然是罗马数字转换,那么它输入的肯定是罗马数字,所以这样以来就简单多了,我们只需要判断怎么计算罗马数字就行了。
那么怎么计算呢,横线不用判断,因为4000以内不用划横线,所以就是加减的事情了,主要判断什么时候加,什么时候减,当当前的数小于后一个数时,那么就应该减去当前的数,除此之外都能该加上该数,即使数字重复,其实也是加,因为重复几次就是几倍,相当于加了几次。

第一种代码如下:

int romanToInt(char* s) {
    int length = strlen(s);
    int *sn = (int *)malloc(sizeof(int) * length);
    for (int i = 0; i < length; i++){
        switch (s[i]){
            case 'I': sn[i] = 1;
            break;
            case 'V': sn[i] = 5;
            break;
            case 'X': sn[i] = 10;
            break;
            case 'L': sn[i] = 50;
            break;
            case 'C': sn[i] = 100;
            break;
            case 'D': sn[i] = 500;
            break;
            case 'M': sn[i] = 1000;
            break;
            default:
            break;
        }
    }
    int sum = sn[0];
    for (int i = 1; i < length; i++){
        if (sn[i] > sn[i-1]) sum = sum - 2 * sn[i-1];
        sum += sn[i];
    }
    free(sn); 
    return sum;
}

第二种

int romanToInt(char* s) {
    int length = strlen(s);
    int sn[256];
    sn['I'] = 1; sn['V'] = 5; sn['X'] = 10; sn['L'] = 50; sn['C'] = 100; sn['D'] = 500; sn['M'] = 1000;
    int sum = sn[s[0]];
    for (int i = 1; i < length; i++){
        if (sn[s[i]] > sn[s[i-1]]) sum = sum - 2 * sn[s[i-1]];
        sum += sn[s[i]];
    }
    return sum;
}

结果显示,这两种代码的耗时没有什么分别,那么switch语句还是效率挺高的。

Lowest Common Ancestor of a Binary Search Tree

Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.

According to the definition of LCA on Wikipedia: “The lowest common
ancestor is defined between two nodes v and w as the lowest node in T
that has both v and w as descendants (where we allow a node to be a
descendant of itself).”

    _______6______
   /              \
___2__          ___8__
/      \        /      \
0      _4       7       9
      /  \
      3   5

For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a
node can be a descendant of itself according to the LCA definition.

这道题的大意就是给定一个顺序二叉树,给定两个节点,找出两个节点最低的共同父节点。

二叉树,考虑的思路肯定是递归,那么怎么递归?很简单,从根结点进入,开始比较,有三种情况,

  1. 根结点的大小严格的在两个节点中间,那么从此根结点往下,两个节点就位于两个不同的子树了,所以下面不可能出现共同父节点了,所以返回该root
  2. 其中一个节点等于根节点,由题意可知,这种情况它们的共同父节点就是这个等于根结点的节点
  3. 两个节点同时严格的大于根结点,或者严格的小于根结点,那么问题就又成了题目中的类型,如果大于根结点,那么两个节点都在右子树,所以递归调用函数,传入右子树根结点,小于类似。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {
    if (!root)
        return NULL;

    if (root->val >= p->val && root->val <= q->val ||
        root->val <= p->val && root->val >= q->val)
        return root;
    if (root->val > p->val && root->val > q->val)
        return lowestCommonAncestor(root->left, p, q);
    if (root->val < p->val && root->val < q->val)
        return lowestCommonAncestor(root->right, p, q);
}

Number of 1 Bits

Write a function that takes an unsigned integer and returns the number of ’1’ bits it has (also known as the Hamming weight).

For example, the 32-bit integer ’11’ has binary representation
00000000000000000000000000001011, so the function should return 3.

给定一个32位整数,算出该数二进制表示形式中的1的个数。

有个比较简单的思路,那就是移位,大部分人也就是用的这个思路,只要n不等于0,就移位,如果当前为奇数就加一

int hammingWeight(uint32_t n) {
    int count = 0;
    while (n){
        if (n % 2 == 1)count ++;     
        n = n >> 1;
    }
    return count;
}

还有一种思路,不用判断奇偶,计数的变量count每次加上n&1,这样如果个位是0,就相当于加了0

int hammingWeight(uint32_t n) {
    int count = 0;
    while (n){
        count = count + (n & 1);     
        n = n >> 1;
    }
    return count;
}

但是在dicuss里面发现了一个很有技巧的代码,以前没有发现这个规律,

n与n-1相与,会消掉最左边的一个1

所以代码就成了这样:

    int count = n ? 1 : 0;
    while(n &= (n-1)) count++;
    return count;
}

Remove Duplicates from Sorted List

Given a sorted linked list, delete all duplicates such that each element appear
only once.

For example, Given 1->1->2, return 1->2. Given 1->1->2->3->3, return
1->2->3.

在排序好的连表中删除重复的节点

思路很简单,从头遍历,如果第一个等于第二个,那么就删除一个。如果不是继续向前走。
两种写法,一种两个指针,一种一个指针

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* deleteDuplicates(struct ListNode* head) {
    if (!head)
        return NULL;
    struct ListNode *p, *q;
    p = head;
    q = head->next;
    while (q){
        if (p->val == q->val){p->next = q->next; q = p->next;}
        else {p = q; q = q->next;}
    }
    return head;
}

一个指针

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* deleteDuplicates(struct ListNode* head) {
    if (!head)
        return NULL;
    struct ListNode *p;
    p = head;
    while (p && p->next){
        if (p->val == p->next->val){p->next = p->next->next;}
        else {p = p->next;}
    }
    return head;
}

分析:一个指针省空间费时间,两个指针,非空间省时间。

你可能感兴趣的:(leetcode)