栈
链表
双指针
题目描述
在一个大小为 n
且 n
为 偶数 的链表中,对于 0 <= i <= (n / 2) - 1
的 i
,第 i
个节点(下标从 0 开始)的孪生节点为第 (n-1-i)
个节点 。
比方说,n = 4
那么节点 0
是节点 3
的孪生节点,节点 1
是节点 2
的孪生节点。这是长度为 n = 4
的链表中所有的孪生节点。
孪生和 定义为一个节点和它孪生节点两者值之和。
给你一个长度为偶数的链表的头节点 head
,请你返回链表的 最大孪生和 。
示例 1:
输入: head = [5,4,2,1]
输出: 6
解释:
节点 0 和节点 1 分别是节点 3 和 2 的孪生节点。孪生和都为 6 。
链表中没有其他孪生节点。
所以,链表的最大孪生和是 6 。
示例 2:
输入: head = [4,2,2,3]
输出: 7
解释:
链表中的孪生节点为:
- 节点 0 是节点 3 的孪生节点,孪生和为 4 + 3 = 7 。
- 节点 1 是节点 2 的孪生节点,孪生和为 2 + 2 = 4 。
所以,最大孪生和为 max(7, 4) = 7 。
示例 3:
输入: head = [1,100000]
输出: 100001
解释:
链表中只有一对孪生节点,孪生和为 1 + 100000 = 100001 。
提示:
链表的节点数目是 [2, 105 ]
中的 偶数 。
1 <= Node.val <= 105
解法
方法一:链表转成列表(数组)求解
时间复杂度 $O(n)$,空间复杂度 $O(n)$。
Python3 Java C++ Go TypeScript Rust
1
2
3
4
5
6
7
8
9
10
11
12
13 # Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution :
def pairSum ( self , head : Optional [ ListNode ]) -> int :
s = []
while head :
s . append ( head . val )
head = head . next
n = len ( s )
return max ( s [ i ] + s [ - ( i + 1 )] for i in range ( n >> 1 ))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 /**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public int pairSum ( ListNode head ) {
List < Integer > s = new ArrayList <> ();
for (; head != null ; head = head . next ) {
s . add ( head . val );
}
int ans = 0 , n = s . size ();
for ( int i = 0 ; i < ( n >> 1 ); ++ i ) {
ans = Math . max ( ans , s . get ( i ) + s . get ( n - 1 - i ));
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 /**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public :
int pairSum ( ListNode * head ) {
vector < int > s ;
for (; head != nullptr ; head = head -> next ) s . push_back ( head -> val );
int ans = 0 , n = s . size ();
for ( int i = 0 ; i < ( n >> 1 ); ++ i ) ans = max ( ans , s [ i ] + s [ n - i - 1 ]);
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 /**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func pairSum ( head * ListNode ) int {
var s [] int
for ; head != nil ; head = head . Next {
s = append ( s , head . Val )
}
ans , n := 0 , len ( s )
for i := 0 ; i < ( n >> 1 ); i ++ {
if ans < s [ i ] + s [ n - i - 1 ] {
ans = s [ i ] + s [ n - i - 1 ]
}
}
return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 /**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function pairSum ( head : ListNode | null ) : number {
const arr = [];
let node = head ;
while ( node ) {
arr . push ( node . val );
node = node . next ;
}
const n = arr . length ;
let ans = 0 ;
for ( let i = 0 ; i < n >> 1 ; i ++ ) {
ans = Math . max ( ans , arr [ i ] + arr [ n - 1 - i ]);
}
return ans ;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 // Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
// pub val: i32,
// pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
// #[inline]
// fn new(val: i32) -> Self {
// ListNode {
// next: None,
// val
// }
// }
// }
impl Solution {
pub fn pair_sum ( head : Option < Box < ListNode >> ) -> i32 {
let mut arr = Vec :: new ();
let mut node = & head ;
while node . is_some () {
let t = node . as_ref (). unwrap ();
arr . push ( t . val );
node = & t . next ;
}
let n = arr . len ();
let mut ans = 0 ;
for i in 0 .. n >> 1 {
ans = ans . max ( arr [ i ] + arr [ n - 1 - i ]);
}
ans
}
}
方法二:快慢指针 + 反转链表 + 双指针
时间复杂度 $O(n)$,空间复杂度 $O(1)$。
Python3 Java C++ Go TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 # Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution :
def pairSum ( self , head : Optional [ ListNode ]) -> int :
def reverse ( head ):
dummy = ListNode ()
curr = head
while curr :
next = curr . next
curr . next = dummy . next
dummy . next = curr
curr = next
return dummy . next
slow , fast = head , head . next
while fast and fast . next :
slow , fast = slow . next , fast . next . next
pa = head
q = slow . next
slow . next = None
pb = reverse ( q )
ans = 0
while pa and pb :
ans = max ( ans , pa . val + pb . val )
pa = pa . next
pb = pb . next
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 /**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public int pairSum ( ListNode head ) {
ListNode slow = head ;
ListNode fast = head . next ;
while ( fast != null && fast . next != null ) {
slow = slow . next ;
fast = fast . next . next ;
}
ListNode pa = head ;
ListNode q = slow . next ;
slow . next = null ;
ListNode pb = reverse ( q );
int ans = 0 ;
while ( pa != null ) {
ans = Math . max ( ans , pa . val + pb . val );
pa = pa . next ;
pb = pb . next ;
}
return ans ;
}
private ListNode reverse ( ListNode head ) {
ListNode dummy = new ListNode ();
ListNode curr = head ;
while ( curr != null ) {
ListNode next = curr . next ;
curr . next = dummy . next ;
dummy . next = curr ;
curr = next ;
}
return dummy . next ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 /**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public :
int pairSum ( ListNode * head ) {
ListNode * slow = head ;
ListNode * fast = head -> next ;
while ( fast && fast -> next ) {
slow = slow -> next ;
fast = fast -> next -> next ;
}
ListNode * pa = head ;
ListNode * q = slow -> next ;
slow -> next = nullptr ;
ListNode * pb = reverse ( q );
int ans = 0 ;
while ( pa ) {
ans = max ( ans , pa -> val + pb -> val );
pa = pa -> next ;
pb = pb -> next ;
}
return ans ;
}
ListNode * reverse ( ListNode * head ) {
ListNode * dummy = new ListNode ();
ListNode * curr = head ;
while ( curr ) {
ListNode * next = curr -> next ;
curr -> next = dummy -> next ;
dummy -> next = curr ;
curr = next ;
}
return dummy -> next ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 /**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func pairSum ( head * ListNode ) int {
reverse := func ( head * ListNode ) * ListNode {
dummy := & ListNode {}
curr := head
for curr != nil {
next := curr . Next
curr . Next = dummy . Next
dummy . Next = curr
curr = next
}
return dummy . Next
}
slow , fast := head , head . Next
for fast != nil && fast . Next != nil {
slow , fast = slow . Next , fast . Next . Next
}
pa := head
q := slow . Next
slow . Next = nil
pb := reverse ( q )
ans := 0
for pa != nil {
ans = max ( ans , pa . Val + pb . Val )
pa = pa . Next
pb = pb . Next
}
return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 /**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function pairSum ( head : ListNode | null ) : number {
let fast = head ;
let slow = head ;
while ( fast ) {
fast = fast . next . next ;
slow = slow . next ;
}
let prev = null ;
while ( slow ) {
const next = slow . next ;
slow . next = prev ;
prev = slow ;
slow = next ;
}
let left = head ;
let right = prev ;
let ans = 0 ;
while ( left && right ) {
ans = Math . max ( ans , left . val + right . val );
left = left . next ;
right = right . next ;
}
return ans ;
}
GitHub