面试算法题-03

题目描述:

给定一个单向链表的头指针和一个结点指针,实现一个函数在o(1)时间删除该结点。

基本思路:

通常我们删除某个节点都是从头开始遍历到需要删除节点的前一个节点。然后使得该节点的next指向删除节点的next即可,这样看来删除一个节点的复杂度为O(n)。然而我们其实遍历的目的只是想获取想要删除节点的前一个节点。

那么我们可以这样考虑:我们把要删除节点下一个节点的值赋值到当前节点,然后将当前节点的下一个节点删除即可。

比如:

一个链表3->2->5->7->9,给定的指针指向5也就是说要删除5这个结点。我们将结点5下一个结点的值赋值给需要删除的节点即:3->2->7->7->9,然后再p->next=p->next->next即可删除。

但是,如果要删除的结点是尾结点,它没有下一个结点,怎么办?我们可仍然从链表的头结点开始,顺序遍历到该结点的前一个结点,并完成删除操作。

最后还需注意,如果链表中只有一个结点,而我们又要删除链表的头结点(也是尾结点),此时我们在删除结点后,还需要把链表的头结点设置为NULL。

代码:

void DeleteNode(ListNode** headNode, ListNode** deleteNode) {

    if((*headNode)==NULL || (*deleteNode)==NULL) {

        return;
    }
    ListNode *temp = *headNode;
    ListNode* deleteNextNode = (*deleteNode)->nextNode;
    if(deleteNextNode == NULL) {

        while((*deleteNode)!=temp->nextNode && temp!=NULL) {
            temp = temp->nextNode
        }
        if(temp != NULL) temp->nextNode=NULL;
        delete (*deleteNode);
        (*deleteNode)=NULL;
    }else {

        (*deleteNode)->value = deleteNextNode->value;
        (*deleteNode)->nextNode = deleteNextNode->nextNode;
        delete deleteNextNode;
        deleteNextNode = NULL;
    }
}

题目:给定一个函数原型Power(double base, int exponent),要求实现该函数,并且不能使用库函数也不用考虑大数问题。

分析:

  1. 最简单的实现Power函数是直接利用for循环,这样时间复杂度为O(n)。

  2. 我们可以利用快速幂来求解,这样就可以把时间复杂度降低到O(logn)

  3. 注意几个问题

    (1)base是否为0,如果是0则0的几次幂都是0

    (2)exponent是否为0,如果为0则返回1;如果小于0则要先求正次幂然后再利用倒数x^(-5) = 1/(x^5);如果是正数则正常求解

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
using namespace std;
const double eps = 1e-9;
bool isEqual(double n, double m) {

    if((n-m)<eps && (n-m)>-eps) return true;
    else return false;
}
double QuickPower(double base, int exponent) {

    double ans=1;
    while(exponent){
        if(exponent&1) {

            ans *= base;
        }
        base *= base;
        exponent >>= 1;
    }
    return ans;
}
double Power(double base, int exponent) {
    if(isEqual(base,0.0)) return 0;
    if(exponent == 0) return 1;
    double ans = QuickPower(base, abs(exponent));
    if(exponent<0) {

        ans = 1.0/ans;
    }
    return ans;


}
int main() {

    double ans = Power(2,4);
    printf("%lf\n", ans);

    return 0;
}

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
void ReOrderArr(int* arrNum, int n) {
    if(arrNum==NULL || n<=0) return;
    int l=0, r=n-1;
    while(l<=r) {
        if(arrNum[l]&1==1) {
            if((arrNum[r]&1)==0) {

                r--;
            }
            l++;
        }
        else {
            if(arrNum[r]&1==1) {

                int temp=arrNum[r];
                arrNum[r]=arrNum[l];
                arrNum[l]=temp;
                l++,r--;
            }
            else r--;
        }

    }

}
int main() {
    int arr[]={2,3,5,6,8,1,7};
    ReOrderArr(arr,7);
    for(int i=0; i<7; i++) printf("%d\n",arr[i]);
    return 0;
}

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
struct ListNode {
    int value;
    ListNode* nextNode;
};
ListNode* BuildList(ListNode **headNode) {
    if(*headNode != NULL) return *headNode;
    *headNode = new ListNode();

    (*headNode)->value=1;
    (*headNode)->nextNode=NULL;
    ListNode *pre = *headNode;
    for(int i=2; i<=5; i++) {
        ListNode *temp = new ListNode();
        temp->value = i;
        temp->nextNode = NULL;
        pre->nextNode = temp;
        pre = temp;
    }
}

void OutputList(ListNode* headNode) {
    if(headNode == NULL) {
        return;
    }
    ListNode *temp = headNode;
    while(temp != NULL) {
        printf("%d\n", temp->value);
        temp = temp->nextNode;
    }


}
void DeleteNode(ListNode** headNode, ListNode** deleteNode) {

    if((*headNode)==NULL || (*deleteNode)==NULL) {

        return;
    }
    ListNode *temp = *headNode;
    ListNode* deleteNextNode = (*deleteNode)->nextNode;
    if(deleteNextNode == NULL) {

        while((*deleteNode)!=temp->nextNode && temp!=NULL) {
            temp = temp->nextNode;
        }
        if(temp != NULL) temp->nextNode=NULL;
        delete (*deleteNode);
        (*deleteNode)=NULL;
    }else {

        (*deleteNode)->value = deleteNextNode->value;
        (*deleteNode)->nextNode = deleteNextNode->nextNode;
        delete deleteNextNode;
        deleteNextNode = NULL;
    }
}
//获得倒数k个链表结点
ListNode*  GetKthFromTail(ListNode* headNode, int k) {

    if(headNode==NULL || k<=0) return NULL;
    ListNode *p1 = headNode;
    ListNode *p2 = headNode;
    int count=1;
    while((count<k)&&p1!=NULL) {
        p1=p1->nextNode;
        count++;
    }
    if(p1==NULL) return NULL;
    while(p1->nextNode != NULL) {
        p1=p1->nextNode;
        p2=p2->nextNode;
    }
    return p2;

}
int main() {
    ListNode *headNode = NULL;
    BuildList(&headNode);
    OutputList(headNode);
    ListNode *l = GetKthFromTail(headNode,2);
    printf("%d\n", l->value);
    DeleteNode(&headNode,&l);
    OutputList(headNode);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值