题解 | #链表内指定区间反转#

链表内指定区间反转

http://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 *
 * C语言声明定义全局变量请加上static,防止重复定义
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param head ListNode类 
 * @param m int整型 
 * @param n int整型 
 * @return ListNode类
 */
struct ListNode* ReverseList_two(struct ListNode* head, int a, int b ) 
{    
    if (a == b)
        return head;
    
    // write code here
    int i =1;
    struct ListNode *r = head;
    
    struct ListNode *s = NULL;
    struct ListNode *z = head;
    
    struct ListNode *sa = NULL;
    struct ListNode *za = NULL;
    struct ListNode *xa = NULL;
    
    struct ListNode *sb = NULL;
    struct ListNode *zb = NULL;
    struct ListNode *xb = NULL;
    
    while(z) // 遍历完整个链表
    {
        if (i == a) // 记录 a 处的 上一个 这一个 下一个
        {
            sa = s;
            za = z;
            xa = z->next;
        }
        else if (i == b) // 记录 a 处的 上一个 这一个 下一个
        {
            sb = s;
            zb = z;
            xb = z->next;
            
            if(a == 1) // 如果交换的是第一个,修改储存的返回值
                r = zb;
            break;
        }
        s = z;
        z = z->next;
        i++;
    }
    
    if (sa) // a 是第一个,没有上一个,跳过
    sa->next = zb; // a 的上一个的下一个改成 b 的这一个
    if (sb != za) // b 的上一个的下一个和 a 的这一个相同,表示 ab 连续
    sb->next = za; // b 的上一个的下一个改成 a 的这一个
    zb->next = zb != xa ? xa : za; // b 的下一个 改成 a 的下一个, 如果 a 的下一个就是 b ,表示 ab 连续, b 的下一个就是 a
    za->next = xb; // a 的下一个 改成 b 的下一个
    
    return r; // 返回链表头
}


struct ListNode* ReverseList(struct ListNode* head, int n1, int n2) 
{
    if (n1 == n2 || head == NULL || head->next == NULL)
        return head;
    
    struct ListNode* h = head;
    struct ListNode* a = NULL; // n1 -1
    struct ListNode* b = head; // n2 + 1
    struct ListNode* c = head->next; // n1
    
    int n=1;
    
    while(1)
    {
        if (n == n1-1) 
            a = b;
        if (n == n2) 
            break;
        b = c;
        c = c->next;
        n++;
    }
    b = c;
    c = a ? a->next : head;
    
    struct ListNode* s = a; 
    struct ListNode* z = c; 
    struct ListNode* x = z->next;
    
    n = 0;
    while(n++ <= n2 - n1)
    {
        x = z->next;
        z->next = s;
        s = z;
        z = x;
    }
    
    c->next = b;
    if (a)
        a->next = s;
    else
        head = s;
    
    return head; // 返回 上一个    
}

// 主函数调用 在2种方法之间切换
struct ListNode* reverseBetween(struct ListNode* head, int a, int b ) 
{    
    if (1)
    {
        return ReverseList(head, a, b); // 一个区间内整体反序
    }
    else
    {
        for (int i=0; i<=(b-a)/2; i++)
        {
            head = ReverseList_two(head, a+i, b-i); // 单独调换2个节点
        }
        return head;
    }
}
全部评论

相关推荐

10-24 11:10
山西大学 Java
若梦难了:哥们,面试挂是很正常的。我大中厂终面挂,加起来快10次了,继续努力吧。
点赞 评论 收藏
分享
10-09 22:05
666 C++
找到工作就狠狠玩CSGO:报联合国演讲,报电子烟设计与制造
点赞 评论 收藏
分享
评论
点赞
1
分享
牛客网
牛客企业服务